用Json.Net反序列化以两种不同方式序列化的值 [英] Deserialize a value serialized in two different ways with Json.Net

查看:92
本文介绍了用Json.Net反序列化以两种不同方式序列化的值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个与此班相似的班:

I have a class similar to this one:

public class Values
{
    public int BestValue { get; set; }
    public List<string> AllValues { get; set; }
}

该类可能(由于历史原因)存储为<​​/p>

This class could be (because of history) be stored either as

"MyFirstValue"  /* if only one value */

{ "BestValue" : 0, "AllValues" : ["DefaultValue", "OtherValue"] }

如何使用JsonConverter自动反序列化? (或任何其他解决方案.)

How can I deserialize this automatically using a JsonConverter? (Or any other solution.)

推荐答案

您将需要创建

You will need to create a custom JsonConverter for this purpose:

internal class ValuesConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return typeof(Values).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var tokenType = reader.SkipComments().TokenType;
        if (tokenType == JsonToken.Null)
            return null;
        var value = existingValue as Values ?? (Values)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
        if (tokenType == JsonToken.Date)
        {
            // Avoid annoying bug that converts date strings to local format described in 
            // https://stackoverflow.com/questions/35166060/json-net-get-specific-json-date-value
            value.AllValues = new List<string> { JToken.Load(reader).ToString(Formatting.None).Trim('"') };
        }
        else if (tokenType.IsPrimitive())
        {
            value.AllValues = new List<string> { (string)JToken.Load(reader) };
        }
        else
        {
            serializer.Populate(reader, value);
        }
        return value;
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}

public static partial class JsonExtensions
{
    public static JsonReader SkipComments(this JsonReader reader)
    {
        while (reader.TokenType == JsonToken.Comment && reader.Read())
            ;
        return reader;
    }

    public static bool IsPrimitive(this JsonToken tokenType)
    {
        switch (tokenType)
        {
            case JsonToken.Integer:
            case JsonToken.Float:
            case JsonToken.String:
            case JsonToken.Boolean:
            case JsonToken.Undefined:
            case JsonToken.Null:
            case JsonToken.Date:
            case JsonToken.Bytes:
                return true;
            default:
                return false;
        }
    }   
}

然后按如下所示将其应用于您的类型:

Then apply it to your type as follows:

[JsonConverter(typeof(ValuesConverter))]
public class Values
{
    public int BestValue { get; set; }
    public List<string> AllValues { get; set; }
}

或者将其添加到 JsonSerializerSettings.Converters ,然后修改您的设置,如 JsonSerializerSettings和Asp.Net Core 所示.

Or, add it to JsonSerializerSettings.Converters then modify your settings as shown in JsonSerializerSettings and Asp.Net Core.

注释-

  • 通过将 CanWrite 设置为假写入JSON时可以使用默认序列化.

  • By setting CanWrite to false one can use default serialization when writing to JSON.

当JSON值不是字符串时, JsonSerializer.Populate() 用于通过默认反序列化来填充Values的内容.

When the JSON value is not a string, JsonSerializer.Populate() is used to fill in the contents of Values via default deserialization.

通过使用 ContractResolver.ResolveContract(objectType).DefaultCreator() 来构建Values对象,可以支持对Values的子类(如果有)进行反序列化.

By using ContractResolver.ResolveContract(objectType).DefaultCreator() to construct the Values object, deserialization of subclasses of Values (if any) can be supported.

工作示例.Net小提琴此处.

Working sample .Net fiddle here.

这篇关于用Json.Net反序列化以两种不同方式序列化的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆