c# - 使用 JSON.NET 序列化时如何将属性从接口(interface)继承到对象

标签 c# json serialization inheritance json.net

<分区>

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.Text;
using System.IO;
using System.Runtime.Serialization;
using Newtonsoft.Json.Serialization;
using System.Linq;
using System.Reflection;
public interface IParent
{
    [JsonProperty]
    int Id {get;set;}
}

[JsonObject(MemberSerialization.OptIn)]
public class Parent : IParent
{
    public int Id { get;set; }  
    public string Name {get;set;}   
}

public class Serializer
{
    public static void Main()
    {

        var parent = new Parent() { Id = 1, Name ="Parent"};        
        var sb = new StringBuilder();
                var sw = new StringWriter(sb);

                var settings = new JsonSerializerSettings()
                       {
                           NullValueHandling = NullValueHandling.Ignore                            
                       };

            var output = JsonConvert.SerializeObject(parent, Formatting.None, settings);
                Console.WriteLine(output);
            Console.ReadKey();
    }
}

在上面的代码中,输出是{}。是否可以将输出序列化为 {"Id":1}

最佳答案

这是个坏主意。

话虽如此,Newtonsoft 为您提供了一种更改序列化内容的方法:在这种情况下,您可以子类化 DefaultContractResolver。并覆盖 CreateProperty

问题是,根据接口(interface)的属性决定何时选择加入序列化并不容易。一方面,一个类可能会使用相互冲突的序列化指令实现多个接口(interface)。此外,反序列化一个对象到声明为冲突接口(interface)(例如)的变量中是行不通的。它很脆弱且不安全(它允许外部代码指定实例显示的数据)。

如果您必须这样做,下面的代码适用于您的情况:

public class InterfaceContractResolver : DefaultContractResolver, IContractResolver
{
    public InterfaceContractResolver() : this(false) { }
    public InterfaceContractResolver(bool shareCache) : base (shareCache) {}

    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        var property = base.CreateProperty(member, memberSerialization);
        var interfaces = member.DeclaringType.GetInterfaces();
        foreach (var @interface in interfaces)
        {
            foreach (var interfaceProperty in @interface.GetProperties())
            {
                // This is weak: among other things, an implementation 
                // may be deliberately hiding an interface member
                if (interfaceProperty.Name == member.Name && interfaceProperty.MemberType == member.MemberType)
                {
                    if (interfaceProperty.GetCustomAttributes(typeof(JsonPropertyAttribute), true).Any())
                    {
                        property.Ignored = false;
                        return property;
                    }
                }
            }
        }
        return property;
    }

}

然后,当您创建序列化器时,在设置中将解析器实例传递给它:

var settings = new JsonSerializerSettings()
{
    NullValueHandling = NullValueHandling.Ignore,
    ContractResolver = new InterfaceContractResolver(true)
};

关于c# - 使用 JSON.NET 序列化时如何将属性从接口(interface)继承到对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5951043/

相关文章:

javascript - 选择序列化形式中缺少的元素?

c# - LINQ 2 实体,如何在 linq 查询中检查 DateTime.HasValue

json - Mongoose:将数据添加到返回的结果集中

c# - 使用泛型在编译时强制执行有效结构

json - 莫时无视场

java - 从 JSON 对象获取数组

c# - 关闭/忽略 xsd 代码生成中指定的字段后缀

serialization - 将氧化钠的公钥序列化为 JSON

c# - 使用分组依据以删除重复项

c# - 使用数据表中的文本填充文本框 - 组合框