对象数据类型的 Json 序列化

本文关键字:序列化 Json 数据类型 对象 | 更新日期: 2023-09-27 18:28:57

public class MyClass
{ 
    public object BidAutoObject { get; set; }
    public bool IsApplied { get; set; }
}

有一个像上面这样的类,我正在从上面的类对象创建 Json 字符串。属性"投标自动对象"的类型为"对象"。对象可能是"CxDays"或"AMPM"。它是动态设置的。我正在使用牛顿软件。JsonConvert.SerializeObject 将 C# 对象序列化为 Json 字符串。Json 序列化的输出就像

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

所以我无法从上面的 json 字符串中确定"BidAutoObject 类型是"CxDays"还是"AMPM"。如何在序列化过程中添加类型信息。我需要向"投标自动对象"添加任何属性吗?

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"。我们有一个使用"Json序列化程序设置"的选项。当我们设置 TypeNameHandling = TypeNameHandling.Auto 时 - 这将添加一个 $type 属性,仅用于声明的类型(即 Base(与实例类型(即派生(不匹配的实例。但它显示了该类的完整命名空间。现在我只想在 Json 字符串中显示类名而不是全名空间。

对象数据类型的 Json 序列化

我想您要查找的是JsonSerializerSettings中需要添加以进行反序列化的TypeNameHandling。只需将其设置为 TypeNameHandling.Auto,这将为类型不等于声明类型的实例向 json 添加一个类型属性。

如果您出于某种原因不希望程序集名称和命名空间名称出现在 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
}

原型小提琴。

有关另一个自定义绑定程序

示例,请参阅文档中的自定义序列化绑定程序。