Reputation: 8199
There is a piece of string I'd like to deserialize with DataContractJsonSerializer
. There is a member in the JSON string that may be an object sometimes or a string other times. Like so:
{ a: 1, b: 2, c: "c" }
or
{ a: 1, b: 2, c: {c1: 3, c2: 4} }
I know the structure of the object in the second case (let's call that class Inner
), but how can DataContractJsonSerializer
convert an object of two possible types?
I tried making an explicit and implicit cast operator to convert from string
to Inner
, but it isn't getting hit. An InvalidCastException
keeps on getting thrown.
Upvotes: 1
Views: 504
Reputation: 237
I had a similar situation, where an API was returning either an array of objects, or just the single object not in an array if there was only one result. I was completely unable to get the DataContractJsonSerializer to do this. I ended up having to switch to the JSON.NET library and fiddle with JsonConverters a bit to get it working.
In your DataContract, declare 'c' as type Inner.
[DataMember(Name = "c")]
public Inner C { get; set; }
Then write a JsonConverter to examine the token type and do the right thing when the deserializer attempts to deserialize an Inner.
internal class StringOrInnerConverter : JsonConverter {
public override bool CanConvert(Type objectType) {
return objectType == typeof(Inner);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) {
var ser = new JsonSerializer();
if (reader.TokenType == JsonToken.StartObject) {
var inn = ser.Deserialize<Inner>(reader);
return inn;
} else if (reader.TokenType == JsonToken.String) {
var str = ser.Deserialize<string>(reader);
return (Inner)str; // Or however you want to convert string to Inner
} else {
return default(Inner);
}
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {
throw new System.NotImplementedException();
}
}
Upvotes: 1