使用自定义类型鉴别器告诉 JSON.net 要反序列化哪种类型的类层次结构 [英] Using a custom type discriminator to tell JSON.net which type of a class hierarchy to deserialize

查看:35
本文介绍了使用自定义类型鉴别器告诉 JSON.net 要反序列化哪种类型的类层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有以下类层次结构:

Suppose I have the following class hierarchy:

public abstract class Organization
{
    /* properties related to all organizations */
}

public sealed class Company : Organization
{
     /* properties related to companies */
} 

public sealed class NonProfitOrganization : Organization
{
     /* properties related to non profit organizations */
}

是否可以让 json.net 使用属性(比如类型"或鉴别器")来确定对象的类型当它反序列化组织时?例如,以下内容应该反序列化 Company 的一个实例.

Is it possible to have json.net use property (say "type" or "discriminator") to determine which type the object when it deserializes the organization? For example, the following should deserialize an instance of Company.

{
   "type": "company"
   /* other properties related to companies */
}

以下内容应该反序列化 NonProfitOrganization 的一个实例.

And the following should deserialize an instance of NonProfitOrganization.

{
   "type": "non-profit"
   /* other properties related to non profit */
}

当我调用以下内容时:

Organization organization = JsonConvert.DeserializeObject<Organization>(payload);

其中有效负载是上述 JSON 片段.我查看了在属性或类上设置TypeNameHandling"但它序列化了整个 .NET 类型,当类定义在不同的命名空间和程序集中时,它在客户端和服务器之间不是可移植的".

where payload is the above JSON snippets. I had a look at setting the "TypeNameHandling" on properties or classes but it serializes the whole .NET type, which isn't "portable" between the client and server when the classes are defined in different namespaces and assemblies.

我宁愿将类型定义为一种中立的方式,用任何语言编写的客户端都可以使用它来确定正在序列化的对象类型的实际类型.

I'd rather define the type is a neutral manner which clients written in any language can use to determine the actual type of the object type being serialized.

推荐答案

如果您还在寻找,这里有一个例子:http://james.newtonking.com/archive/2011/11/19/json-net-4-0-release-4-bug-fixes.aspx

In case you are still looking, here is an example: http://james.newtonking.com/archive/2011/11/19/json-net-4-0-release-4-bug-fixes.aspx

这将允许您创建基于表的映射:

This will allow you to create a table based mapping:

public class TypeNameSerializationBinder : SerializationBinder
{
    public TypeNameSerializationBinder(Dictionary<Type, string> typeNames = null)
    {
        if (typeNames != null)
        {
            foreach (var typeName in typeNames)
            {
                Map(typeName.Key, typeName.Value);
            }
        }
    }

    readonly Dictionary<Type, string> typeToName = new Dictionary<Type, string>();
    readonly Dictionary<string, Type> nameToType = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);

    public void Map(Type type, string name)
    {
        this.typeToName.Add(type, name);
        this.nameToType.Add(name, type);
    }

    public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
    {
        var name = typeToName.Get(serializedType);
        if (name != null)
        {
            assemblyName = null;
            typeName = name;
        }
        else
        {
            assemblyName = serializedType.Assembly.FullName;
            typeName = serializedType.FullName;                
        }
    }

    public override Type BindToType(string assemblyName, string typeName)
    {
        if (assemblyName == null)
        {
            var type = this.nameToType.Get(typeName);
            if (type != null)
            {
                return type;
            }
        }
        return Type.GetType(string.Format("{0}, {1}", typeName, assemblyName), true);
    }
}

该代码有一个小缺陷,如果在类型唯一但名称已被使用的情况下尝试类型名称映射,则在类型到名称的映射已经添加后,Map 方法将抛出异常,离开表处于不一致状态.

The code has a slight defect in that if a type name mapping is attempted where the type is unique but the name is already used, the Map method will throw an exception after the type-to-name mapping is already added leaving the table in an inconsistent state.

这篇关于使用自定义类型鉴别器告诉 JSON.net 要反序列化哪种类型的类层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆