gpt4 book ai didi

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

转载 作者:太空宇宙 更新时间:2023-11-03 12:53:10 30 4
gpt4 key购买 nike

我们有一种情况,其中一个正在通过 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/

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com