23

上下文:我需要传递一个包含大量属性/字段的对象(从中间层到 UI 层)。在这个属性列表中,一个是没有从 JSON 字符串格式正确反序列化的 Version 类型。我在 XML 上选择了 JSON 格式,因为 JSON 序列化为字符串将返回短字符串结果。

问题:System.Version 没有正确反序列化。我尝试了两个不同的 .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}

使用Newtonsoft .NET 库的代码片段 2,但结果相同:

        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

28

Newtonsoft.Json库在命名空间中提供了一组通用转换器Newtonsoft.Json.Converters,包括VersionConverter可用于序列化和反序列化的转换器System.Version

请注意,您必须同时使用VersionConverter两者进行序列化和反序列化
这是因为标准序列化会生成例如:{"Major":1,"Minor":2,"Build":3,"Revision":0,"MajorRevision":0,"MinorRevision":0}VersionConverter反序列化需要一个简单的字符串,如"1.2.3".

所以用法是:

using Newtonsoft.Json;
using Newtonsoft.Json.Converters;  

string s = JsonConvert.SerializeObject(version, new VersionConverter());
Version v = JsonConvert.DeserializeObject<Version>(s, new VersionConverter());

我不确定Newtonsoft.Json包含该转换器的第一个版本是什么。我的有它,它是 5.0.6。

于 2013-09-09T21:51:34.430 回答
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 将使用您的转换器之一,如果它们匹配SomeClass.

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