对象数据类型的 Json 序列化

Posted

技术标签:

【中文标题】对象数据类型的 Json 序列化【英文标题】:Json serialization for Object Data Type 【发布时间】:2016-04-07 04:13:26 【问题描述】:
public class MyClass
 
    public object BidAutoObject  get; set; 
    public bool IsApplied  get; set; 

我有一个像上面这样的类,我正在从上面的 Class 对象创建 Json 字符串。属性“BidAutoObject”属于“对象”类型。该对象可能是“CxDays”或“AMPM”。它是动态设置的。我正在使用 newtonsoft.JsonConvert.SerializeObject 将 C# 对象序列化为 Json 字符串。 Json 序列化的输出是这样的

"BidAutoObject": 
    "IsSun": true,
    "IsMon": false,
    "IsTue": true,
    "IsWed": true,
    "IsThu": false,
    "IsFri": true,
    "IsSat": true

所以我无法从上面的json字符串中识别“BidAutoObject类型是“CxDays”还是“AMPM”。如何在序列化过程中添加类型信息。是否需要在“BidAutoObject”中添加任何属性?

public class CxDays

    public bool IsSun  get; set; 
    public bool IsMon  get; set; 
    public bool IsTue  get; set; 


public class AMPM

   public bool AM  get; set; 
   public bool PM  get; set; 
   public bool MIX  get; set; 

而不是 ""BidAutoObject": 在 Json 字符串中,我需要 json 字符串中的类对象名称,例如 "CxDays" 或 "AMPM"。我们有一个使用 "Jsonserializer setting" 的选项。当我们设置 TypeNameHandling = TypeNameHandling.Auto - 这将只为声明类型(即 Base)与实例类型(即 Derived)不匹配的实例添加 $type 属性。但它显示了该类的完整命名空间。现在我只想显示Json 字符串中的类名而不是全名空间。

【问题讨论】:

这看起来确实像 XY 问题。你想做什么? 如果您作为开发人员无法识别它是哪个具体对象,您如何期望 JSON.NET 等框架能够识别它? 但它显示了该类的完整命名空间——那么问题是什么?根据您的描述,听起来 Json.NET 正在成功地序列化和反序列化类型信息。 我已经更新了问题 【参考方案1】:

我猜你正在寻找的是JsonSerializerSettings 中的TypeNameHandling,你需要添加它以进行反序列化和序列化。 只需将其设置为TypeNameHandling.Auto,这将为类型不等于声明类型的实例添加一个类型属性到 json。

【讨论】:

【参考方案2】:

如果出于某种原因(为什么?)您只是不希望程序集名称和命名空间名称出现在 JSON 中,您可以创建自己的 DefaultSerializationBinder 的自定义子类,然后将其设置在 JsonSerializerSettings.Binder 中:

public class DefaultAssemblyBinder : DefaultSerializationBinder

    public string DefaultAssemblyName  get; private set; 
    public string DefaultNamespaceName  get; private set; 

    public DefaultAssemblyBinder(string defaultAssemblyName, string defaultNamespaceName)
    
        this.DefaultAssemblyName = defaultAssemblyName;
        this.DefaultNamespaceName = defaultNamespaceName;
    

    public override Type BindToType(string assemblyName, string typeName)
    
        if (!string.IsNullOrEmpty(DefaultAssemblyName))
        
            if (string.IsNullOrEmpty(assemblyName))
                assemblyName = DefaultAssemblyName;
        
        if (!string.IsNullOrEmpty(DefaultNamespaceName))
        
            if (typeName != null && !typeName.Contains("."))
                typeName = DefaultNamespaceName + "." + typeName;
        
        return base.BindToType(assemblyName, typeName);
    

    public override void BindToName(Type serializedType, out string assemblyName, out string typeName)
    
        base.BindToName(serializedType, out assemblyName, out typeName);
        if (!string.IsNullOrEmpty(DefaultAssemblyName) && assemblyName != null)
            if (assemblyName == DefaultAssemblyName)
                assemblyName = null;
        if (!string.IsNullOrEmpty(DefaultNamespaceName) && typeName != null)
        
            int index = typeName.LastIndexOf('.');
            if (index < 0)
                throw new JsonSerializationException(string.Format("Type 0 does not exist in any namespace, but a default namespace 1 has been set", serializedType.FullName, DefaultNamespaceName));
            if (index == DefaultNamespaceName.Length && string.Compare(DefaultNamespaceName, 0, typeName, 0, index, StringComparison.Ordinal) == 0)
                typeName = typeName.Substring(index + 1);
        
    

然后,稍后:

        var test = new MyClass  IsApplied = true, BidAutoObject = new CxDays  IsMon = false, IsSun = true, IsTue = false  ;

        var settings = new JsonSerializerSettings  TypeNameHandling = TypeNameHandling.Auto, Binder = new DefaultAssemblyBinder(typeof(MyClass).Assembly.FullName, typeof(MyClass).Namespace) ;
        var json = JsonConvert.SerializeObject(test, Formatting.Indented, settings);
        Console.WriteLine(json);

创建以下 JSON:


  "BidAutoObject": 
    "$type": "CxDays",
    "IsSun": true,
    "IsMon": false,
    "IsTue": false
  ,
  "IsApplied": true

原型fiddle。

有关另一个自定义活页夹示例,请参阅文档中的 Custom SerializationBinder。

【讨论】:

以上是关于对象数据类型的 Json 序列化的主要内容,如果未能解决你的问题,请参考以下文章

JSON数据类型

将JSON字符串反序列化为指定的.NET对象类型

Flask API TypeError:“响应”类型的对象不是 JSON 可序列化的

Python序列化之Json基础

Java 数据类型的自定义 JSON 序列化

“Mycart”类型的对象在 Django 中不是 JSON 可序列化的