【问题标题】:Deserializing JSON with varying schemas使用不同的模式反序列化 JSON
【发布时间】:2018-08-08 21:50:33
【问题描述】:

我将 JSON.Net 与 .NET 4.7 一起使用。

在我调用的 API 中,我可以看似随机地为同一个调用获取两种错误 json :(.

错误类型 1:

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

错误类型 2:

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

如您所见,Msg 改变了它的结构。我想要一个通用的 POCO 来反序列化,但是当 Msg 发生变化时如何?

JsonConvert.DeserializeObject<MyCommonPoco>(theJson);

【问题讨论】:

  • 只有这两个选项吗?
  • 第二个 JSON 格式不正确。尝试上传到jsonlint.com,你会得到Error: Parse error on line 4:。您能否提供有效的 JSON 样本?
  • 我打字不好。问题更多是关于改变模式
  • @poke 是的,只有两种
  • 您需要一个自定义创建转换器:newtonsoft.com/json/help/html/CustomCreationConverter.htm

标签: c# json json.net


【解决方案1】:

您可以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 数组可以包含原始字符串或复杂对象。该对象可以包含MessageCode,或两者兼有。

您会为此选择最常见的数据结构,一种能够表示所有信息的数据结构。例如,这意味着您必须将该原始字符串包装到兼容的对象中。

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-11-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-05-01
    • 1970-01-01
    相关资源
    最近更新 更多