假设我有以下类层次结构:
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 */
}
Run Code Online (Sandbox Code Playgroud)
是否有可能让json.net使用属性(比如"type"或"discriminator")来确定对象在反序列化组织时的类型?例如,以下内容应反序列化Company的实例.
{
"type": "company"
/* other properties related to companies */
}
Run Code Online (Sandbox Code Playgroud)
以下应该反序列化NonProfitOrganization的实例.
{
"type": "non-profit"
/* other properties related to non profit */
}
Run Code Online (Sandbox Code Playgroud)
当我打电话给以下人时:
Organization organization = JsonConvert.DeserializeObject<Organization>(payload);
Run Code Online (Sandbox Code Playgroud)
其中payload是上面的JSON片段.我看一下在属性或类上设置" TypeNameHandling ",但是它序列化了整个.NET类型,当在不同的命名空间和程序集中定义类时,它在客户端和服务器之间不是"可移植的".
我宁愿定义类型是一种中性的方式,用任何语言编写的客户端都可以用它来确定被序列化的对象类型的实际类型.
在这个链接上,在备注部分提到了" TypeNameHandling".在什么情况下,如果使用序列化/反序列化来自外部源的JSON会有害SerializationBinder?一个工作的例子将不胜感激.
我看到使用JSON.Net,如果$type属性指定了JSON对象的特定类型,我可以解码多态对象.在我看过的所有示例中,$type包括命名空间.是否可以使这项工作包括一个简单的类型名称而不需要汇编?如果可能的话,我很乐意为JsonSerializer指定默认程序集.
我可以使用以下命令反序列化JSON:
public class SingleAssemblyJsonTypeBinder : SerializationBinder
{
private readonly Assembly _assembly;
private Dictionary<string, Type> _typesBySimpleName = new Dictionary<string, Type>(StringComparer.OrdinalIgnoreCase);
private Dictionary<Type,string> _simpleNameByType = new Dictionary<Type, string>();
public SingleAssemblyJsonTypeBinder(Assembly assembly)
{
_assembly = assembly;
_typesBySimpleName = new Dictionary<string, Type>();
foreach (var type in _assembly.GetTypes().Where(t => t.IsPublic))
{
if (_typesBySimpleName.ContainsKey(type.Name))
throw new InvalidOperationException("Cannot user PolymorphicBinder on a namespace where multiple public types have same name.");
_typesBySimpleName[type.Name] = type;
_simpleNameByType[type] = type.Name;
}
}
public override Type BindToType(string …Run Code Online (Sandbox Code Playgroud) 所以我有两个类,如下所示。它们都在同一个命名空间和同一个共享项目中。
public class Person{
public string Name{get;set;}
}
public class EmployedPerson : Person{
public string JobTitle{get;set;}
}
Run Code Online (Sandbox Code Playgroud)
当我将这些项目序列化为 rabbitmq 时,我将序列化为基类,如下所示:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Objects
};
JsonConvert.SerializeObject(input, settings)
Run Code Online (Sandbox Code Playgroud)
但是在反序列化时我遇到了问题。我希望能够执行如下所示的操作,其中我将反序列化为基类,然后检查它是否是继承类型。
类型检查:
Person person = Deserialize<Person>(e.Body, Encoding.Unicode);
if (person is EmployedPerson)
{
logger.LogInformation("This person has a job!");
}
Run Code Online (Sandbox Code Playgroud)
反序列化设置:
JsonSerializerSettings settings = new JsonSerializerSettings
{
TypeNameAssemblyFormatHandling = TypeNameAssemblyFormatHandling.Simple,
TypeNameHandling = TypeNameHandling.Auto
};
Run Code Online (Sandbox Code Playgroud)
反序列化逻辑:
private static T Deserialize<T>(byte[] data, Encoding encoding) where T : class
{ …Run Code Online (Sandbox Code Playgroud)