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

查看:72
本文介绍了使用自定义类型区分符告诉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 使用属性(例如"type"或"discriminator")来确定对象的类型什么时候反序列化组织?例如,以下应反序列化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.

推荐答案

如果您仍在寻找,请参考以下示例:

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天全站免登陆