【问题标题】:Serialize field of type Type with FormatterAssemblyStyle.Simple in Json.NET在 Json.NET 中使用 FormatterAssemblyStyle.Simple 序列化 Type 类型的字段
【发布时间】:2017-02-05 09:21:55
【问题描述】:

我在 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);
}

这将产生以下 JSON 字符串:

{
  "$type": "Foo, Assembly-CSharp",
  "type": "System.Void, mscorlib, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"
}

如您所见,FormatterAssemblyStyle.Simple 已用于$type,但FormatterAssemblyStyle.Full 已用于type

这是我想要的输出:

{
  "$type": "Foo, Assembly-CSharp",
  "type": "System.Void, mscorlib"
}

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

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

    根据sources

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

    如果对象类型为Type类型,则格式化为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);
        }
    }
    

    并像这样使用:

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

    【讨论】:

      猜你喜欢
      • 2011-03-20
      • 2015-12-10
      • 1970-01-01
      • 1970-01-01
      • 2013-04-02
      • 2012-07-04
      • 1970-01-01
      • 2014-12-27
      • 1970-01-01
      相关资源
      最近更新 更多