Reputation: 68750
I use JSON.Net with .NET 4.7.
In an API I call, I can get two kinds of error jsons for the same call seemingly randomly :(.
Error Type 1:
{
"Code": 0,
"Msg": ["Some Warning"]
}
Error Type 2:
{
"Code": 0,
"Msg": [
{"Error": 5 },
{"Error": 6 }
]
}
As you can see, the Msg
changes its structure. I'd like to have a common POCO to deserialize into, but how when the Msg
changes?
JsonConvert.DeserializeObject<MyCommonPoco>(theJson);
Upvotes: 1
Views: 677
Reputation: 387667
You can write a custom JsonConverter
that handles different types. You could for example have the following 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 }
]
}
In this example, the Msg
array can contain primitive strings, or a complex object. And that object can contain a Message
, a Code
, or both.
You would choose the most common data structure for this, one that is able to represent all that information. That means for example that you will have to wrap that primitive string into a compatible object.
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; }
}
You can then use a custom
And then, with a custom JsonConverter
, you could parse the above 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();
}
}
This would be one way to use that converter:
// 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);
Upvotes: 5