代码之家  ›  专栏  ›  技术社区  ›  Ian Vink

使用不同模式反序列化JSON

  •  1
  • Ian Vink  · 技术社区  · 6 年前

    我将JSON.Net与.Net 4.7结合使用。

    在我调用的一个API中,对于同一个调用,我可以随机得到两种错误json:(。

    错误类型1:

    {
       "Code": 0,
       "Msg": ["Some Warning"]
    }
    

    错误类型2:

    {
        "Code": 0,
        "Msg": [
              {"Error": 5 },
              {"Error": 6 }
        ]
    }
    

    如你所见 Msg 改变它的结构。我想有一个共同的POCO来反序列化,但是当 味精 变化?

    JsonConvert.DeserializeObject<MyCommonPoco>(theJson);
    
    1 回复  |  直到 6 年前
        1
  •  4
  •   poke    6 年前

    你可以 write a custom JsonConverter 处理不同类型的。例如,您可以使用以下JSON:

    {
        "Code": 0,
        "Msg": [
            "A single string",
            { "Message": "An object with a message" },
            { "Message": "An object with a message and a code", "Code": 5 },
            { "Code": 5 }
        ]
    }
    

    在本例中 Msg 数组可以包含基元字符串或复杂对象。这个对象可以包含 Message ,一个 Code ,或者两者都有。

    您可以为此选择最常用的数据结构,即能够表示所有这些信息的数据结构。例如,这意味着您必须将原始字符串包装成兼容的对象。

    public class Error
    {
        public int Code { get; set; }
        public ErrorMessage[] Msg { get; set; }
    }
    
    public class ErrorMessage
    {
        public string Message { get; set; }
        public int? Code { get; set; }
    }
    

    然后可以使用自定义

    然后,按照惯例 JsonConverter ,可以解析上面的JSON:

    public class ErrorMessageConverter : JsonConverter
    {
        public override bool CanConvert(Type objectType)
            => objectType == typeof(ErrorMessage);
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            // handle the primitive string
            if (reader.TokenType == JsonToken.String)
                return new ErrorMessage { Message = (string)reader.Value };
    
            // handle a complex object; just assume that it is an `ErrorMessage` here
            else if (reader.TokenType == JsonToken.StartObject)
                return JObject.Load(reader).ToObject<ErrorMessage>();
    
            throw new NotSupportedException();
        }
    
        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    

    这是使用转换器的一种方法:

    // the single quotes are just here to make it more readable; JSON.NET support this
    // although it isn’t valid JSON
    var json = @"{
        'Code': 0,
        'Msg': [
            'A single string',
            { 'Message': 'An object with a message' },
            { 'Message': 'An object with a message and a code', 'Code': 5 },
            { 'Code': 5 }
        ]
    }";
    
    var settings = new JsonSerializerSettings()
    settings.Converters.Add(new ErrorMessageConverter());
    
    var result = JsonConvert.DeserializeObject<Error>(json, settings);
    

    Successfully parsed result