Json.NET并不在对象的列表或字典中保留基本类型信息.有解决办法吗?



下面的示例说明了Json的一个基本缺陷。. NET的类型处理:

List<object> items = new List<object>() {Guid.NewGuid(),DateTime.Now};
var settings = new JsonSerializerSettings() { TypeNameHandling=TypeNameHandling.All };
var json = JsonConvert.SerializeObject<List<object>>(value,settings);

生成以下JSON:

{"$type":"System.Collections.Generic.List`1[[System.Object, mscorlib]], mscorlib","$values":["9d7aa4d3-a340-4cee-baa8-6af0582b8acd","2014-07-28T21:03:17.1287029-04:00"]}
如您所见,列表项丢失了它们的类型信息。对相同的JSON进行反序列化将得到一个仅包含字符串的列表。

这个问题之前在codeplex上报告过,并敷衍地关闭了,声明包含类型信息会使JSON过于混乱。我很惊讶,在往返一致性被打破的情况下,我们没有提供一个单独的选项来包含基本类型信息。

https://json.codeplex.com/workitem/23833

我希望返回的数据具有与离开时相同的类型信息。有人有什么建议或解决方法来纠正这种不受欢迎的行为吗?

谢谢,克里斯

下面是使用自定义JsonConverter的解决方案:

public sealed class PrimitiveJsonConverter : JsonConverter
{
    public PrimitiveJsonConverter()
    {
    }
    public override bool CanRead
    {
        get
        {
            return false;
        }
    }
    public override bool CanConvert(Type objectType)
    {
        return objectType.IsPrimitive;
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        switch (serializer.TypeNameHandling)
        {
            case TypeNameHandling.All:
                writer.WriteStartObject();
                writer.WritePropertyName("$type", false);
                switch (serializer.TypeNameAssemblyFormat)
                {
                    case FormatterAssemblyStyle.Full:
                        writer.WriteValue(value.GetType().AssemblyQualifiedName);
                        break;
                    default:
                        writer.WriteValue(value.GetType().FullName);
                        break;
                }
                writer.WritePropertyName("$value", false);
                writer.WriteValue(value);
                writer.WriteEndObject();
                break;
            default:
                writer.WriteValue(value);
                break;
        }
    }
}

用法如下:

JsonSerializerSettings settings = new JsonSerializerSettings() 
{ 
    TypeNameHandling = TypeNameHandling.All,
};
settings.Converters.Insert(0, new PrimitiveJsonConverter());
return JsonConvert.SerializeObject(myDotNetObject, settings);

我目前正在使用这个解决方案来序列化一个可以包含原语的IDictionary<string, object>实例

将其整合并进行测试。显然,这需要单元测试,更多的是概念验证。如果你想要一个肮脏的解决方案来让你开始。

https://github.com/xstos/Newtonsoft.Json/commit/8d3507cbba78f7096a82e42973e56d69c9541c42

相关内容

  • 没有找到相关文章

最新更新