23

コンテキスト: 多数のプロパティ/フィールドを含むオブジェクトを (中間層レイヤーから UI レイヤーに) 渡す必要があります。このプロパティのリストの 1 つは、JSON 文字列形式から正しく逆シリアル化されていないバージョン タイプです。文字列へのJSONシリアル化は短い文字列の結果を返すため、XMLよりもJSON形式を選択しました。

問題: System.Version が正しく逆シリアル化されません。2 つの異なる .NET ライブラリを試しました。以下は、それぞれのコード スニペットです。

ServiceStack .NET ライブラリを使用したコード スニペット 1 :

        var version = new Version(1, 2, 3, 0);
        string reportJSON = JsonSerializer.SerializeToString<Version>(version);
        //{"Major":1,"Minor":2,"Build":3,"Revision":0,"MajorRevision":0,"MinorRevision":0}


        Version report2 = JsonSerializer.DeserializeFromString<Version>(reportJSON);
        string reportJSON2 = JsonSerializer.SerializeToString<Version>(report2);
        //{"Major":0,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}

コード スニペット 2 はNewtonsoft .NET ライブラリを使用していますが、結果は同じです。

        var version = new Version(1, 2, 3, 0);
        string reportJSON = JsonConvert.SerializeObject(version);
        //{"Major":1,"Minor":2,"Build":3,"Revision":0,"MajorRevision":0,"MinorRevision":0}


        Version report2 = JsonConvert.DeserializeObject<Version>(reportJSON);
        string reportJSON2 = JsonConvert.SerializeObject(report2);
        //{"Major":0,"Minor":0,"Build":-1,"Revision":-1,"MajorRevision":-1,"MinorRevision":-1}

これを修正する方法は?または、他のどの JSON.NET ライブラリが正しく機能しますか?

4

2 に答える 2

10

Versionクラスのプロパティにはセッターがありません。対応するプライベート フィールドの値を返すだけです。したがって、デシリアライザーはそれらの値を変更できません。

しかし、Json.NET を使用すると、Versionクラスの逆シリアル化を処理するカスタム コンバーター クラスを作成できます。

注意:このコードは十分にテストされていません...

public class VersionConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // default serialization
        serializer.Serialize(writer, value);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // create a new Version instance and pass the properties to the constructor
        // (you may also use dynamics if you like)
        var dict = serializer.Deserialize<Dictionary<string, int>>(reader);
        return new Version(dict["Major"], dict["Minor"], dict["Build"], dict["Revision"]);
    }

    public override bool CanConvert(Type objectType)
    {
        return objectType == typeof(Version);
    }
}

次に、コンバーターを使用することを指定する必要があります。

var v = new Version(1, 2, 3, 4);
string json = JsonConvert.SerializeObject(v);

var v2 = JsonConvert.DeserializeObject<Version>(json, new VersionConverter());

Json.NET は、指定したコンバーターのいずれかを使用するかどうかを決定します。したがって、以下に示すように、いつでもコンバーターを指定できます。内のタイプと一致する場合、Json.NET はコンバーターの 1 つを使用しますSomeClass

var result = JsonConvert.DeserializeObject<SomeClass>(json, new VersionConverter());
于 2012-11-01T12:43:01.073 に答える