【问题标题】:Json serialization for Object Data Type对象数据类型的 Json 序列化
【发布时间】: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 正在成功地序列化和反序列化类型信息。
  • 我已经更新了问题

标签: c# json serialization 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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2017-05-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-12-19
      相关资源
      最近更新 更多