Json.NET custom serialization/deserialization of a third party type

During deserialization, Json.Net looks at the classes that you are deserializing into in order to determine what types to create, and by extension, whether to call your converter. So, if you deserialize into a class that has a Vector4 property, your converter will be called. If you deserialize into something nebulous like dynamic or object or JObject, then Json.Net will not know to call your converter, and therefore the deserialized object hierarchy will not contain any Vector4 instances.

Let's take a simple example to make this concept more clear. Say we have this JSON:

{
    "PropA": [ 1.0, 2.0, 3.0, 4.0 ],
    "PropB": [ 5.0, 6.0, 7.0, 8.0 ]
}

Clearly, both 'PropA' and 'PropB' in the above JSON could represent a Vector4 (or at least what I infer to be a Vector4 from your converter code-- I am not actually familiar with the OpenTK library). But, as you noticed, there is no type information in the JSON that says that either property should be a Vector4.

Let's try to deserialize the JSON into the following class using your converter. Here, PropA must contain a Vector4 or null since it is strongly typed, while PropB could be anything.

public class Tester
{
    public Vector4 PropA { get; set; }
    public object PropB { get; set; }
}

Here is the test code:

class Program
{
    static void Main(string[] args)
    {
        string json = @"
        {
            ""PropA"": [ 1.0, 2.0, 3.0, 4.0 ],
            ""PropB"": [ 5.0, 6.0, 7.0, 8.0 ]
        }";

        try
        {
            Tester t = JsonConvert.DeserializeObject<Tester>(json),
                                              new VectorConverter());

            DumpObject("PropA", t.PropA);
            DumpObject("PropB", t.PropB);
        }
        catch (Exception ex)
        {
            Console.WriteLine(ex.GetType().Name + ": " + ex.Message);
        }
    }

    static void DumpObject(string prop, object obj)
    {
        if (obj == null)
        {
            Console.WriteLine(prop + " is null");
        }
        else
        {
            Console.WriteLine(prop + " is a " + obj.GetType().Name);
            if (obj is Vector4)
            {
                Vector4 vector = (Vector4)obj;
                Console.WriteLine("   X = " + vector.X);
                Console.WriteLine("   Y = " + vector.Y);
                Console.WriteLine("   Z = " + vector.Z);
                Console.WriteLine("   W = " + vector.W);
            }
            else if (obj is JToken)
            {
                foreach (JToken child in ((JToken)obj).Children())
                {
                    Console.WriteLine("   (" + child.Type + ") " 
                                             + child.ToString());
                }
            }
        }
    }
}

// Since I don't have the OpenTK library, I'll use the following class
// to stand in for `Vector4`.  It should look the same to your converter.

public class Vector4
{
    public Vector4(float x, float y, float z, float w)
    {
        X = x;
        Y = y;
        Z = z;
        W = w;
    }

    public float W { get; set; }
    public float X { get; set; }
    public float Y { get; set; }
    public float Z { get; set; }
}

When I run the test code, here is the output I get:

PropA is a Vector4
   X = 1
   Y = 2
   Z = 3
   W = 4
PropB is a JArray
   (Float) 5
   (Float) 6
   (Float) 7
   (Float) 8

So you can see, for PropA, Json.Net used the converter to create the Vector4 instance (otherwise we would have gotten a JsonSerializationException), while for PropB, it did not (otherwise, we would have seen PropB is a Vector4 in the output).

As for the second part of your question, what to do if your converter is given JSON that is not what it is expecting. You have two choices-- return null, like you are doing, or throw an exception (such as a JsonSerializationException). If your converter is being called, you know that Json.Net is trying to populate a Vector4 object. If it were not, then your converter would not have been called. So, if you can't populate it because the JSON is wrong, you have to decide whether it is acceptable that the Vector4 be null, or is it better to error out. It is a design decision that depends on what you are trying to do in your project.

Have I explained that clearly?


Comments

  1. Amir

    • 2015/6/10

    During deserialization, Json.Net looks at the classes that you are deserializing into in order to determine what types to create, 

  2. Colombo

    • 2016/10/26

    During deserialization, Json.Net looks at the classes that you are deserializing into in order to determine what types to create, and by extension, whether to call your converter. So, if you deserialize into a class that has a Vector4 property, your converter will be called.

  3. Morgan

    • 2016/7/1

    We can implement JSON Serialization/Deserialization by using NET is a third-party library that helps conversion between JSON text and .

  4. Hernandez

    • 2020/6/24

    In case of ASP.NET Core 3.1 or above the default json serializer is the System.Text.Json. In order to use Json.Net you need to install the Microsoft.AspNetCore.Mvc.NewtonsoftJson package. This exposes a method called AddNewtonsoftJson where you can register the custom converter:

  5. Richard

    • 2016/10/26

    It is easy for humans to read and write and easy for machines to parse Json.NET is a third party library which helps conversion between 

  6. Angelo

    • 2015/10/2

    During serialization or deserialization, a converter is chosen for each JSON element in the following order, listed from highest priority to lowest: [JsonConverter] applied to a property. A converter added to the Converters collection. [JsonConverter] applied to a custom value type or POCO.

  7. Cairo

    • 2020/1/29

    The following scenarios are covered later in this article: Deserialize inferred types to object properties. Support polymorphic deserialization.

  8. Dupont

    • 2016/1/27

    Deserialize into a JSON DOM (document object model) and extract what you need from the DOM. The DOM lets you navigate to a subsection of a JSON payload and deserialize a single value, a custom type, or an array. For information about the JsonNode DOM in .NET 6, see Deserialize subsections of a JSON payload.

  9. Kayson

    • 2016/8/10

    Hi Team, Found an Issue while serializing / Deserializing an ArrayList object Newtonsoft json custom deserializer for property. json.net 

  10. Philip

    • 2015/3/15

    So that’s where we would need a custom json converter. Setup. First thing you need to do is to create a custom class the derives from JsonConverter, and override 3 methods. In the CanConvert method we check if the passed in type can be assigned to our target type WeirdName.

  11. Forrest

    • 2018/9/7

    The web service returned a JSON-formatted array of objects, so I created a .NET object and used the Newtonsoft JSON.Net library to deserialize the array.

  12. Kamryn

    • 2017/12/20

    Json.NET is a third-party library that helps conversion between JSON text and .NET object using the JsonSerializer. The JsonSerializer converts .NET objects into their JSON equivalent text and back again by mapping the .NET object property names to the JSON property names.

  13. Boden

    • 2017/2/28

    The new serializer uses UTF-8 directly. Since Newtonsoft is a 3rd party library and not part of the .NET Framework (BCL or FCL classes), you 

  14. Dominic

    • 2019/6/25

    In the most recent version of the third party Newtonsoft Json converter you can set a constructor with a concrete type relating to the interfaced property.

  15. Thiago

    • 2015/5/28

    I am trying to customize a the serialization of a third-party library class my own custom converter for the type, but the converter appli.

  16. Kyle

    • 2021/7/27

    The advantages of using an external table are: • We can use a custom it also has a third party SerDe like that of JSON SerDe provided by Amazon.

Comments are closed.

Recent Posts