【发布时间】:2018-04-25 02:25:01
【问题描述】:
我遇到了一个关于 Json.Net 的我不理解的有趣场景。
我需要序列化对象以便将它们发布到 API。对象是使用具有某种层次结构的类型创建的。所以在序列化方法中,基本类型用于接收对象/对象并使用 Json.Net 和 TypeNameHandling.Auto 进行序列化。
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace SerializationTest
{
class Program
{
static void Main(string[] args)
{
var dj = new Dj() { Name = "Tim", Label = "UMG", StageName = "Avicii" };
var djJson = JSerializer.Serialize(dj);
var djs = new List<Person>();
djs.Add(dj);
var djsJson = JSerializer.Serialize(djs);
Console.ReadKey();
}
}
public static class JSerializer
{
public static string Serialize(Person person)
{
var result = JsonConvert.SerializeObject(person, Formatting.Indented, new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return result;
}
public static string Serialize(IReadOnlyList<Person> people)
{
var eventModelsSerialized = JsonConvert.SerializeObject(people, Formatting.Indented,
new JsonSerializerSettings
{
TypeNameHandling = TypeNameHandling.Auto
});
return eventModelsSerialized;
}
}
public abstract class Person
{
public string Name { get; set; }
}
public abstract class Artist : Person
{
public string Label { get; set; }
}
public class Dj : Artist
{
public string StageName { get; set; }
}
}
然后发生的事情是: 对于单对象序列化案例,我得到了非常基本的 Json,没有任何类型信息:
{
"StageName": "Avicii",
"Label": "UMG",
"Name": "Tim"
}
而对于对象序列化的列表,我们得到了带有类型信息的 Json:
[
{
"$type": "SerializationTest.Dj, SerializationTest",
"StageName": "Avicii",
"Label": "UMG",
"Name": "Tim"
}
]
这会给服务器端造成混乱。因此,当我只想序列化单个对象时,由于缺少类型信息,服务器端无法对其进行序列化。所以解决方法是创建一个列表来包含对象并序列化为列表。
谁能解释为什么 Json.Net 对这两种情况进行不同的序列化?提前致谢。
【问题讨论】:
-
@dbc 感谢您的 cmets。这些链接解释了如何为根对象启用 $type ,这确实有助于我改进序列化单个对象的代码。但是他们没有提到为什么在绑定序列化列表时会自动添加 $type 。你对此还有什么想法吗?
-
因为在序列化列表时,
var dj = new Dj()不再是根对象——List<Person>()是根对象。所以TypeNameHandling.Auto现在适用。 -
@dbc 是正确的。谢谢。我想我现在明白了。
标签: c# .net json serialization json.net