为什么JSON字符串中的System.Version没有正确反序列化



Context:我需要将包含大量属性/字段的对象(从中间层传递到UI层)。在这个属性列表中,有一个是Version类型,它没有从JSON字符串格式中正确反序列化。我选择了JSON格式而不是XML,因为对字符串的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}

代码段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库可以正常工作?

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

请注意,必须同时使用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。

Version类的属性没有setter。它们只是返回相应私有字段的值。因此,反序列化程序无法更改它们的值。

但是使用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自行决定是否使用您指定的转换器之一。因此,您可以始终指定转换器,如下所示。如果您的转换器与SomeClass中的类型匹配,Json.NET将使用其中一个转换器。

var result = JsonConvert.DeserializeObject<SomeClass>(json, new VersionConverter());

相关内容

  • 没有找到相关文章

最新更新