c# - 使用 BindingList 时 json.net 中的反序列化问题

标签 c# json.net

我们遇到一种情况,通过 json.net 序列化和反序列化的字段中的一个是我们的一个对象上的绑定(bind)列表属性。当尝试反序列化该字段时,我们得到一个异常:

An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll

Additional information: Error resolving type specified in JSON 'WpfApplication1.Wrapper1[[System.ComponentModel.BindingList1[[System.String, mscorlib]], System]], WpfApplication1'. Path 'Potato.$type', line 4, position 131.

为了重现,我创建了一个小样本:

public class ClassToSerialize
{
    public Wrapper<BindingList<string>> Potato { get; set; }
}

public class Wrapper<T>
{
    public Wrapper()
    {
    }

    public Wrapper(T item)
    {
        Value = item;
    }

    #region Properties

    [JsonProperty]
    public T Value { get; set; }

    #endregion
}

测试是:

var objectToSerialize = new ClassToSerialize
{
    Potato = new Wrapper<BindingList<string>>(new BindingList<string>
    {
        "tomato",
        "basil"
    })
};

string serializedPotato = JsonSerializer<ClassToSerialize>.Serialize(objectToSerialize, true);
ClassToSerialize deserializedPotato = JsonSerializer<ClassToSerialize>.Deserialize(serializedPotato);

序列化代码很简单:

public class JsonSerializer<T> where T : class
{
    public static string Serialize(T item, bool isComplexType = false)
    {
        if (isComplexType)
        {
            string serializedJson = JsonConvert.SerializeObject(item, Formatting.Indented, new JsonSerializerSettings
            {
                TypeNameHandling = TypeNameHandling.Objects,
                TypeNameAssemblyFormat = System.Runtime.Serialization.Formatters.FormatterAssemblyStyle.Simple
            });

            return serializedJson;
        }

        return JsonConvert.SerializeObject(item);
    }

    public static T Deserialize(string serializedItem)
    {
        var deserializedObject = JsonConvert.DeserializeObject<T>(serializedItem, new JsonSerializerSettings
        {
            TypeNameHandling = TypeNameHandling.Objects
        });

        return deserializedObject;
    }
}

此处发生错误:ClassToSerialize deserializedPotato = JsonSerializer<ClassToSerialize>.Deserialize(serializedPotato);但是如果我将底层集合的类型从 BindingList<T> 更改为至List<T> ,一切正常。

有谁知道这里的问题是什么以及如何解决它?

请注意,我已经测试了未包装的 BindingList<> (即没有包装在另一种类型中)并且效果很好。

非常感谢,

最佳答案

使用 FormatterAssemblyStyle.Simple 似乎有问题。如果我修改你的代码以使用 FormatterAssemblyStyle.Full问题就消失了。

使用简单的程序集名称(在 Json.NET 8.0.2 中),调用 assembly.GetType(typeName)里面 DefaultSerializationBinder.GetTypeFromTypeNameKey(TypeNameKey typeNameKey) 即使组装正确,也会失败。

我不完全确定调用失败的原因,因为所有通用参数类型都存在简单的程序集名称。 Assembly.GetType(string) 的文档不指定如何发现泛型类型名称引用的程序集。 Type.GetType(string) 的文档状态:

GetType only works on assemblies loaded from disk.

之后:

If typeName includes the namespace but not the assembly name, this method searches only the calling object's assembly and Mscorlib.dll, in that order. If typeName is fully qualified with the partial or complete assembly name, this method searches in the specified assembly. If the assembly has a strong name, a complete assembly name is required.

所以也许问题在于 BindingList<T>不在 mscorlib.dll 中(它得到特殊处理),也不在从磁盘加载的 DLL 中(它来自 GAC 中的 System.dll)?

我可以手动重现这种不一致。如果我这样做:

Type.GetType("System.Collections.Generic.List`1[[System.String, mscorlib]],mscorlib")

它有效。然而,

Type.GetType("System.ComponentModel.BindingList`1[[System.String,mscorlib]],System")

失败。

也许你可以 report an issue

关于c# - 使用 BindingList 时 json.net 中的反序列化问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34860022/

相关文章:

c# - 如何在 asp.net 中将 List<> 添加到 List<>

c# - 约束 System.Type 作为类型安全的通用参数

c# - 删除从客户端发送的值列表

c# - 具有大量元素的 WPF 绘图性能

c# - 用于数组和集合的自定义 Newtonsoft JsonConverter 以进行进一步操作

c# - 为什么 Json.NET 试图反序列化我的 get only 属性?

c# - 科学数据可视化和 .NET 框架

c# - 调用 DeserializeObject<Object>( ... ) 时验证 Json 数据

c# - 在 ASP.NET Web API 中抑制 JsonMediaTypeFormatter 的 RequiredAttribute 验证

c# - 在 .NET Core 2.0 中调用 JsonConvert.DeserializeObject<T> 时缺少 System.Security.Permissions