【问题标题】:Deserialize a value serialized in two different ways with Json.Net使用 Json.Net 反序列化以两种不同方式序列化的值
【发布时间】:2018-09-25 12:54:34
【问题描述】:

我有一个类似于这个的类:

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

这个类可以(因为历史)被存储为

"MyFirstValue"  /* if only one value */

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

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

【问题讨论】:

    标签: serialization asp.net-core json.net deserialization


    【解决方案1】:

    您需要为此创建一个custom JsonConverter

    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;
            }
        }   
    }
    

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

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

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

    注意事项-

    工作示例 .Net fiddle here.

    【讨论】:

    • 谢谢!实际上我已经开始实现转换器,但是我缺少“读取”方法中的代码。关于如何实现的文档实际上并不是很清楚...... Populate 方法主要是我所缺少的!我也错过了注册部分,我认为该属性足以注册它。
    • 哼哼,属性就够了:D我看到好几次这些注册没有使用属性,我不太喜欢它们。
    猜你喜欢
    • 1970-01-01
    • 2020-07-17
    • 2017-02-27
    • 1970-01-01
    • 2020-06-08
    • 1970-01-01
    • 2017-11-21
    • 1970-01-01
    相关资源
    最近更新 更多