使用不同的模式反序列化 JSON

Ian*_*ink 1 c# json json.net

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

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

错误类型 1:

{
   "Code": 0,
   "Msg": ["Some Warning"]
}
Run Code Online (Sandbox Code Playgroud)

错误类型 2:

{
    "Code": 0,
    "Msg": [
          {"Error": 5 },
          {"Error": 6 }
    ]
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,Msg它的结构发生了变化。我想要一个通用的 POCO 来反序列化,但是当发生Msg变化时怎么办?

JsonConvert.DeserializeObject<MyCommonPoco>(theJson);
Run Code Online (Sandbox Code Playgroud)

pok*_*oke 5

您可以编写处理不同类型的自定义。JsonConverter例如,您可以有以下 JSON:

\n\n
{\n    "Code": 0,\n    "Msg": [\n        "A single string",\n        { "Message": "An object with a message" },\n        { "Message": "An object with a message and a code", "Code": 5 },\n        { "Code": 5 }\n    ]\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

在此示例中,Msg数组可以包含原始字符串或复杂对象。该对象可以包含 a Message、 aCode或两者。

\n\n

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

\n\n\n\n
public class Error\n{\n    public int Code { get; set; }\n    public ErrorMessage[] Msg { get; set; }\n}\n\npublic class ErrorMessage\n{\n    public string Message { get; set; }\n    public int? Code { get; set; }\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

然后您可以使用自定义

\n\n

然后,使用自定义JsonConverter,您可以解析上面的 JSON:

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

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

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

成功解析结果

\n