Why does Json.NET not include $type for the root object when TypeNameHandling is Auto?

后端 未结 3 1008
谎友^
谎友^ 2021-01-18 06:41

When I set Json.NET to serialize with TypeNameHandling set to TypeNameHandling.Auto, it correctly sets $type for child properties of an object but does not do so for the roo

相关标签:
3条回答
  • 2021-01-18 07:03

    Short answer: it doesn't because it can't.

    As you stated in your question, setting TypeNameHandling to Auto directs Json.Net to include the .NET type name when the actual (run-time) type of the object being serialized is not the same as its declared (compile-time) type. In order to do that, Json.Net needs to know both types for every object.

    For everything inside the root object, this is straightforward: just get the runtime type of the root object via GetType(), then use reflection to get all of its declared properties and their types, and for each one compare the declared type to the actual type to see if they differ. If they do, output the type name.

    But for the root object itself, Json.Net doesn't have access to both types. All the information it has is the object referenced by fido, whose runtime type is Dog. There's no way for Json.Net to discover that the fido variable was declared as Animal, unless you provide that context somehow. And that is exactly why Json.Net provides overloads of SerializeObject which allow you to specify the compile-time type of the object being serialized. You must use one of these overloads if you want the TypeNameHandling.Auto setting to work for the root object.

    0 讨论(0)
  • 2021-01-18 07:16

    Newer versions of Json.Net allow you to pass the expected type to the serialize method

     ser.Serialize(stream, rootObject, typeof(BaseClass));
    

    You can pass the base class to the serialize method and TypeNameHandling.Auto will write the $type if the object and expected type do not match.

    0 讨论(0)
  • 2021-01-18 07:22

    Brian is absolutely correct, Json.NET has no way of knowing the compile-time declared type of the object it's being passed as the value parameter is declared as an object. The easy fix for this was if Json.NET added generic serialize methods so that the compile-time declared type would automatically flow over to Json.NET but the library's author has decided against my proposal for this here.

    As an alternative, I've wrapped all my json (de)serialization needs in a JsonHelper class with generic serialize methods which use the typeof expression to automatically pass the compile-time declared type of the value to be serialized.

    0 讨论(0)
提交回复
热议问题