Json.net序列化特定的私有字段。

63

我有以下的类:

public class TriGrid
{
    private List<HexTile> _hexes;
    //other private fields...
    //other public proprerties
}

我的目标是只序列化_hexes字段,所以我创建了以下ContractResolver:

internal class TriGridContractResolver : DefaultContractResolver
{
    protected override List<MemberInfo> GetSerializableMembers(Type objectType)
    {
        return new List<MemberInfo> { objectType.GetMember("_hexes", BindingFlags.NonPublic | BindingFlags.Instance)[0] };
    }
}

而当我想要序列化TriGrid的实例时,我会这样做:

var settings = new JsonSerializerSettings()
{
    ContractResolver = new TriGridContractResolver()
};
var json = JsonConvert.SerializeObject(someTriGrid, settings);
string strintJson = json.ToString();

但是当我检查 strintJson 的值时,它总是 "{}"_hexes 有元素,不是空的。如果我序列化一个特定的 HexTile,它会按预期工作。我在这里做错了什么吗?


请参见以下链接:https://dev59.com/3Gkw5IYBdhLWcg3wBl-A https://dev59.com/jGAf5IYBdhLWcg3w9Wmu - Ilya
1
@Ilya,根据你提供的第一个SO链接,看起来它序列化了所有私有字段,但我只想序列化一个特定的字段。而你提供的第二个SO链接中使用了CreateProperties,但我要序列化的是一个字段,而不是属性。 - Bsa0
2个回答

132

无需实现自定义DefaultContractResolver。解决方案是在_hexes上放置[JsonProperty],并在所有其他属性和字段上放置[JsonIgnore]


44
同时在该类上使用 [JsonObject(MemberSerialization.OptIn)]。这样 [JsonIgnore] 属性就不再必要了。 - dbc
1
这应该是关于此主题的所有其他问题的答案,它们都进行了自定义实现。只有JsonProperty和JsonIgnore才是更好的解决方案。 - DFTR

12

由于商业模式最终会改变,因此我更喜欢实现ISerializable并使用.NET的创建瞬间的方式(即属性包)。当您需要在运行时对对象进行版本控制时,这是最有效的方法。任何您不想序列化的内容都不要放入属性包中。

特别是,由于JSON.Net(Newtonsoft.Json)也将使用其序列化和反序列化方法进行验证。

using System;
using System.Runtime.Serialization;

[Serializable]
public class Visitor : ISerializable
{
    private int Version;

    public string Name { get; private set; }

    public string IP { get; set: }

    public Visitor()
    {
        this.Version = 2;
    }

    public void ChangeName(string Name)
    {
        this.Name = Name;
    }

    //Deserialize
    protected Visitor(SerializationInfo info, StreamingContext context)
    {
        this.Version = info.GetInt32("Version");
        this.Name = info.GetString("Name");
    }

    //Serialize
    public void GetObjectData(SerializationInfo info, StreamingContext context)
    {
        info.AddValue("Version", this.Version);

        info.AddValue("Name", this.Name);
    }

    [OnDeserialized]
    private void OnDeserialization(StreamingContext context)
    {
        switch (this.Version)
        {
            case 1:
                //Handle versioning issues, if this
                //deserialized version is one, so that
                //it can play well once it's serialized as
                //version two.
                break;
        }
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接