How to deserialize a JSON property that can be two different data types using Json.NET
c#, json, json.net, serialization
Solution
This can be solved by making a custom `JsonConverter` for your `SupplierData` class. Here is what the converter might look like:
class SupplierDataConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(SupplierData));
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
if (token.Type == JTokenType.Object)
{
return token.ToObject<SupplierData>();
}
return null;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
serializer.Serialize(writer, value);
}
}
To use it, all you would need to do is add a `[JsonConverter]` attribute to the `Supplier` property in your `Data` class like this:
public class Data
{
[JsonProperty("supplier")]
[JsonConverter(typeof(SupplierDataConverter))]
public SupplierData Supplier { get; set; }
}
Below is a demonstration of the converter in action. Note that the demo assumes you have some kind of containing object for the `data` property, since the JSON in your question can't stand on its own. I defined a class called `RootObject` for this purpose:
public class RootObject
{
[JsonProperty("data")]
public Data Data { get; set; }
}
The actual demo code follows:
class Program
{
static void Main(string[] args)
{
string json = @"
{
""data"":
{
""supplier"":
{
""id"": 15,
""name"": ""TheOne""
}
}
}";
Console.WriteLine("--- first run ---");
RootObject obj = JsonConvert.DeserializeObject<RootObject>(json);
DumpSupplier(obj.Data.Supplier);
json = @"
{
""data"":
{
""supplier"": false
}
}";
Console.WriteLine("--- second run ---");
obj = JsonConvert.DeserializeObject<RootObject>(json);
DumpSupplier(obj.Data.Supplier);
}
static void DumpSupplier(SupplierData supplier)
{
if (supplier != null)
{
Console.WriteLine("Id: " + supplier.Id);
Console.WriteLine("Name: " + supplier.Name);
}
else
{
Console.WriteLine("(null)");
}
Console.WriteLine();
}
}
And here is the output from the above:
--- first run ---
Id: 15
Name: TheOne
--- second run ---
(null)
Problem
I'm using Json.NET for a project I'm working on. From an external API, I am receiving JSON with properties that are objects, but when they are empty 'false' is passed. For example: ``` data: { supplier: { id: 15, name: 'TheOne' } } ``` Could also be: ``` data: { supplier: false } ``` How should I define the supplier property so that the supplier will be deserialized to a Supplier object or null. Right now I have: ``` public class Data { [JsonProperty("supplier")] public SupplierData Supplier { get; set; } } public class SupplierData { [JsonProperty("id")] public int Id { get; set; } [JsonProperty("name")] public string Name { get; set; } } ``` But now when trying to deserialize when supplier has a value of 'false' it fails. I would like the Supplier property to be null when the JSON value is 'false'. I hope someone knows how to do this. Thanks.