How to serialize only inherited properties of a class using a JsonConverter(如何使用 JsonConverter 仅序列化类的继承属性)
问题描述
我正在尝试仅使用 json.net 序列化类的继承属性.我知道 [JsonIgnore] 属性,但我只想在某些情况下忽略它们,所以我使用了自定义 JsonConverter.
I'm trying to serialize only the inherited properties of a class using json.net. I'm aware of the [JsonIgnore] attribute, but I only want to do ignore them on certain occasion, so I used a custom JsonConverter instead.
这是我的课:
public class EverythingButBaseJsonConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Find properties of inherited class
        var classType = value.GetType();
        var classProps = classType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
        // Remove the overrided properties
        classProps.RemoveAll(t =>
        {
            var getMethod = t.GetGetMethod(false);
            return (getMethod.GetBaseDefinition() != getMethod);
        });
        // Get json data
        var o = (JObject)JToken.FromObject(value);
        // Write only properties from inhertied class
        foreach (var p in o.Properties().Where(p => classProps.Select(t => t.Name).Contains(p.Name)))
            p.WriteTo(writer);
    }
    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        throw new NotImplementedException("");
    }
    public override bool CanRead
    {
        get { return false; }
    }
    public override bool CanConvert(Type objectType)
    {
        return true;
    }
}
当做一个简单的 o.WriteTo(writer);它给出与不使用转换器相同的结果.遍历属性并在属性上使用 WriteTo 时,它适用于基本类型(int、string 等),但我遇到了集合问题.
When doing a simple o.WriteTo(writer); it give the same result as not using a converter. When iterating through properties and using WriteTo on the properties, it works fine for base type (int, string, etc), but I'm having problem with collections.
预期:
{
  "Type": 128,
  "Time": [
    1,
    2,
  ],
  "Pattern": 1,
  "Description": ""
}
得到:
  "Type": 128,
  "Time": [
    1,
    2,
  ]"Pattern": 1,
  "Description": ""
如您所见,该集合缺少,"和结束行部分.我也缺少整个对象的全局 { }.
As you can see, the collection is missing the "," and endline portion. I'm also missing the global { } for the whole object.
我做事的方式正确吗?有没有更简单的方法来获得我想要的结果?
I am doing things the correct way? Is there an easier way to get the result I want?
推荐答案
不确定您的代码为什么不起作用(可能是 Json.NET 错误?).相反,您可以从 JObject 中删除不需要的属性,并在一次调用中编写整个内容:
Not sure why your code doesn't work (maybe a Json.NET bug?).  Instead, you can remove the properties you don't want from the JObject and write the entire thing in one call:
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        // Find properties of inherited class
        var classType = value.GetType();
        var classProps = classType.GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic).ToList();
        // Remove the overrided properties
        classProps.RemoveAll(t =>
        {
            var getMethod = t.GetGetMethod(false);
            return (getMethod.GetBaseDefinition() != getMethod);
        });
        // Get json data
        var o = (JObject)JToken.FromObject(value);
        // Remove all base properties
        foreach (var p in o.Properties().Where(p => !classProps.Select(t => t.Name).Contains(p.Name)).ToList())
            p.Remove();
        o.WriteTo(writer);
    }
或者,您可以创建自己的 合约解析器并过滤掉基础属性和成员:
Alternatively, you could create your own contract resolver and filter out base properties and members:
public class EverythingButBaseContractResolver : DefaultContractResolver
{
    protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
    {
        if (member.ReflectedType != member.DeclaringType)
            return null;
        if (member is PropertyInfo)
        {
            var getMethod = ((PropertyInfo)member).GetGetMethod(false);
            if (getMethod.GetBaseDefinition() != getMethod)
                return null;
        }
        var property = base.CreateProperty(member, memberSerialization);
        return property;
    }
}
然后像这样使用它:
        var settings = new JsonSerializerSettings { ContractResolver = new EverythingButBaseContractResolver() };
        var json = JsonConvert.SerializeObject(rootObject, Formatting.Indented, settings);
                        这篇关于如何使用 JsonConverter 仅序列化类的继承属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持编程学习网!
本文标题为:如何使用 JsonConverter 仅序列化类的继承属性
				
        
 
            
        - CanBeNull和ReSharper-将其用于异步任务? 2022-01-01
 - 在 LINQ to SQL 中使用 contains() 2022-01-01
 - 带问号的 nvarchar 列结果 2022-01-01
 - 在 C# 中异步处理项目队列 2022-01-01
 - 是否可以在 .Net 3.5 中进行通用控件? 2022-01-01
 - 使用 rss + c# 2022-01-01
 - C# 通过连接字符串检索正确的 DbConnection 对象 2022-01-01
 - Azure Active Directory 与 MVC,客户端和资源标识同一 2022-01-01
 - 为什么 C# 中的堆栈大小正好是 1 MB? 2022-01-01
 - Windows 喜欢在 LINUX 中使用 MONO 进行服务开发? 2022-01-01
 
						
						
						
						
						