web-dev-qa-db-ja.com

Json.netは特定のプライベートフィールドをシリアル化します

次のクラスがあります。

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には要素があり、空ではありません。 1つの特定のHexTileをシリアル化すると、期待どおりに機能します。ここで私が間違っているのは何ですか?

30
Bsa0

カスタムDefaultContractResolverを実装する必要はありません。解決策は、[JsonProperty] on _hexesおよび[JsonIgnore]他のすべてのプロパティとフィールド。

72
Bsa0

ビジネスモデルは最終的に変更されるため、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;
        }
    }
}
6
Roy Oliver