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

时间:2016-01-18 16:53:17

标签: c# json.net

我们遇到的情况是,通过json.net进行序列化和反序列化的字段中的一个是我们其中一个对象的绑定列表属性。在尝试反序列化此字段时,我们得到一个例外:

  

类型' Newtonsoft.Json.JsonSerializationException的未处理异常'发生在Newtonsoft.Json.dll

     

其他信息:在JSON' WpfApplication1.Wrapper 1[[System.ComponentModel.BindingList 1 [[System.String,mscorlib]],System]],WpfApplication1'中指定的错误解析类型。 Path' Potato。$ type',第4行,第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<>(即没有换成其他类型)并且工作正常。

非常感谢,

1 个答案:

答案 0 :(得分:1)

似乎使用FormatterAssemblyStyle.Simple时遇到了问题。如果我修改您的代码以使用FormatterAssemblyStyle.Full,问题就会消失。

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

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

  

GetType仅适用于从磁盘加载的程序集。

后来:

  

如果typeName包含命名空间而不包含程序集名称,则此方法仅按顺序搜索调用对象的程序集和Mscorlib.dll。如果typeName完全使用部分或完整程序集名称限定,则此方法将在指定的程序集中搜索。如果程序集具有强名称,则需要完整的程序集名称。

所以问题可能是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