当TypeNameHandling为Auto时,为什么Json.NET不在根对象中包含$ type? [英] Why does Json.NET not include $type for the root object when TypeNameHandling is Auto?

查看:62
本文介绍了当TypeNameHandling为Auto时,为什么Json.NET不在根对象中包含$ type?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当我将Json.NET设置为将TypeNameHandling设置为TypeNameHandling.Auto进行序列化时,它会正确地为对象的子属性设置$ type,但不会为要序列化的根对象设置$ type.为什么?

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 root object being serialized. Why?

请考虑以下再现:

public class Animal
{
    public Animal[] Offspring { get; set; }
}

public class Dog : Animal {}

Animal fido = new Dog
{
    Offspring = new Animal[] { new Dog() }
};

var json = JsonConvert.SerializeObject(fido, 
    new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.Auto
    });

发出到json变量中的Json是:

The Json emitted into the json variable is:

{
    "Offspring": [{
        "$type": "MyApp.Dog, MyApp",
        "Offspring": null
    }]
}

Json.NET 文档表示,对于TypeNameHandling.Auto行为是:

The Json.NET Documentation says that for TypeNameHandling.Auto the behavior is:

当要序列化的对象的类型与其声明的类型不同时,请包括.NET类型名称.

Include the .NET type name when the type of the object being serialized is not the same as its declared type.

我的问题是-为什么菲多没有 "$type": "MyApp.Dog, MyApp",喜欢它的小狗吗? :)

My question is - Why does fido not have "$type": "MyApp.Dog, MyApp", like its puppy? :)

更新:我已经从

UPDATE: I've found out from the accepted answer to this question that I can force $type to be added by doing this:

var json = JsonConvert.SerializeObject(fido,
    typeof(Animal),
    new JsonSerializerSettings
    {
        TypeNameHandling = TypeNameHandling.Auto,
        Formatting = Formatting.Indented
    });

但是我的问题仍然存在-为什么Json.NET根据文档本身不这样做?

But my question still holds - Why does Json.NET not do this by itself as per the documentation?

推荐答案

简短的回答:不是因为不能.

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

正如您在问题中指出的那样,当要序列化的对象的实际(运行时)类型与其声明的名称不同时,将TypeNameHandling设置为Auto会指示Json.Net包含.NET类型名称. (编译时)类型.为了做到这一点,Json.Net需要知道每个对象的两种类型.

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.

对于根对象中的所有内容,这很简单:只需通过GetType()获取根对象的运行时类型,然后使用反射来获取其所有声明的属性及其类型,并对每个声明的类型进行比较到实际类型以查看它们是否不同.如果是这样,则输出类型名称.

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.

但是对于根对象本身,Json.Net不能同时访问这两种类型.它具有的所有信息是fido引用的对象,该对象的运行时类型为Dog.除非您以某种方式提供该上下文,否则Json.Net无法发现fido变量被声明为Animal.这就是Json.Net提供 SerializeObject 的重载的原因.允许您指定要序列化的对象的编译时类型.如果希望TypeNameHandling.Auto设置适用于根对象,则必须使用这些重载之一.

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.

这篇关于当TypeNameHandling为Auto时,为什么Json.NET不在根对象中包含$ type?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆