Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to deserialize a JSON property that can be two different data types using Json.NET

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.

like image 539
Marc Selman Avatar asked Dec 06 '13 19:12

Marc Selman


People also ask

How do I deserialize JSON?

A common way to deserialize JSON is to first create a class with properties and fields that represent one or more of the JSON properties. Then, to deserialize from a string or a file, call the JsonSerializer. Deserialize method.

What is serializing and deserializing JSON?

JSON is a format that encodes objects in a string. Serialization means to convert an object into that string, and deserialization is its inverse operation (convert string -> object).

What is JSON property in C#?

JsonPropertyAttribute indicates that a property should be serialized when member serialization is set to opt-in. It includes non-public properties in serialization and deserialization. It can be used to customize type name, reference, null, and default value handling for the property value.

What is JSON serialization and deserialization in C#?

Serialization is the process of converting . NET objects such as strings into a JSON format and deserialization is the process of converting JSON data into . NET objects.


1 Answers

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) 
like image 179
Brian Rogers Avatar answered Oct 01 '22 12:10

Brian Rogers