I'm getting a json message with a field called "item"
that can be deserialized as class foo or class bar.
How do I implement this in C#?
I assume something like this:
public class FooOrBar
{
// Only one of the two will get populated.
public Foo foo { get; set; }
public Bar bar { get; set; }
bool is_foo;
}
[JsonProperty("item")]
[JsonConverter(typeof(CustomConverter))]
public FooOrBar Item { get; set; }
How do I implement the custom converter for such a case?
Is there a simpler solution?
I'm not sure how Foo
or Bar
is determined in your code, but for now let's assume you have a JSON structure like this:
var json = @"
{
isFoo: true,
item: {}
}";
In which case Foo
or Bar
is determined by isFoo
.
FooOrBar
class could be subjective. I would not define class like that, but use polymorphism:
interface IItem
{
bool IsFoo { get; }
}
class Foo : IItem
{
public bool IsFoo => true;
}
class Bar : IItem
{
public bool IsFoo => false;
}
[JsonConverter(typeof(CustomJsonConverter))]
class MyClass
{
public IItem Item { get; set; }
}
I set CustomJsonConverter
to MyClass
because of the JSON structure I have. I need to use information available in the parent object of item
to determine Foo
or Bar
so I have to set JsonConverter
to the declaring type of Item
property. If you use information available in item
property, you can move converter to the Item
property.
Now implement CustomJsonConverter
like this:
class CustomJsonConverter : JsonConverter
{
public override bool CanConvert(Type objectType) => true;
public override object ReadJson(JsonReader reader, Type objectType,
object existingValue, JsonSerializer serializer)
{
var token = JToken.ReadFrom(reader);
if (token.Type == JTokenType.Null)
{
return null;
}
// Create an instance of MyClass, and set property as per "isFoo".
var obj = new MyClass();
if (token["isFoo"].Value<bool>())
{
obj.Item = new Foo();
}
else
{
obj.Item = new Bar();
}
// Populate properties
serializer.Populate(token.CreateReader(), obj);
return obj;
}
public override void WriteJson(JsonWriter writer, object value,
JsonSerializer serializer)
{
throw new NotSupportedException();
}
}