在 Json.NET 中使用 FormatterAssemblyStyle.Simple 序列化 Type 类型的字段

exo*_*ter 5 c# json json.net

我在 Unity3D 中使用 Json.NET (v90r1) 的 Net20 库,并且尝试使用 Json.NET 序列化 Type 类型的字段。

我发现这FormatterAssemblyStyle会影响自动生成的类型信息,但它似乎不会影响 Type 类型的字段。例如:

using Newtonsoft.Json;
using System.Runtime.Serialization.Formatters;
using UnityEngine;

public class Example : MonoBehaviour
{
    void Start()
    {
        var settings = new JsonSerializerSettings() {
            Formatting = Formatting.Indented,
            TypeNameHandling = TypeNameHandling.All,
            TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple,
        };

        Debug.Log(JsonConvert.SerializeObject(new Foo(), settings));
    }
}

public class Foo
{
    public System.Type type = typeof(void);
}
Run Code Online (Sandbox Code Playgroud)

这将产生以下 JSON 字符串:

{
  "$type": "Foo, Assembly-CSharp",
  "type": "System.Void, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,FormatterAssemblyStyle.Simple已用于$type,但FormatterAssemblyStyle.Full已用于type

这是我想要的输出:

{
  "$type": "Foo, Assembly-CSharp",
  "type": "System.Void, mscorlib"
}
Run Code Online (Sandbox Code Playgroud)

如何使两种类型以相同的方式打印?我无法找到答案,因为大多数搜索结果与序列化私有成员或序列化具有类型信息的类有关,而不是序列化包含类型的类。

Ole*_*nov 5

消息人士透露:

internal static bool TryConvertToString(object value, Type type, out string s)
{
    //...
    type = value as Type;
    if (type != null)
    {
        s = type.AssemblyQualifiedName;
        return true;
    }
    //...
}
Run Code Online (Sandbox Code Playgroud)

如果对象类型为Typetype,则其格式为Type.AssemblyQualifiedName

但是,您可以按照CustomJsonConverter示例为以下内容创建自定义转换器Type

public class TypeConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        if (typeof(System.Type).IsAssignableFrom(value.GetType()))
        {
            // here you decide how much information you really want to dump
            Type type = (Type)value;
            writer.WriteValue(type.FullName + ", " + type.Assembly.GetName().Name);
        }
        else 
        {
            JToken t = JToken.FromObject(value);
            t.WriteTo(writer);
        }
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("Unnecessary because CanRead is false. The type will skip the converter.");
    }

    public override bool CanRead
    {
        get { return false; }
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(System.Type).IsAssignableFrom(objectType);
    }
}
Run Code Online (Sandbox Code Playgroud)

并使用如下:

    var settings = new JsonSerializerSettings()
    {
        Formatting = Formatting.Indented,
        TypeNameHandling = TypeNameHandling.All,
        TypeNameAssemblyFormat = FormatterAssemblyStyle.Simple,
        Converters = { new TypeConverter() } 
    };

    Console.WriteLine(JsonConvert.SerializeObject(new Foo(), settings));
Run Code Online (Sandbox Code Playgroud)