如何使用JsonConverter仅序列化类的继承属性

时间:2015-05-05 21:06:33

标签: c# json json.net

我试图使用json.net仅序列化类的继承属性。我知道[JsonIgnore]属性,但我只想在某些场合忽略它们,所以我使用了自定义的JsonConverter。

这是我的班级:

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(作家);它给出与不使用转换器相同的结果。当迭代属性并在属性上使用WriteTo时,它适用于基类型(int,string等),但我对集合有问题。

预期:

{
  "Type": 128,
  "Time": [
    1,
    2,
  ],
  "Pattern": 1,
  "Description": ""
}

GOT:

  "Type": 128,
  "Time": [
    1,
    2,
  ]"Pattern": 1,
  "Description": ""

正如您所看到的,该系列缺少","和结束部分。我也错过了整个对象的全局{}。

我正在以正确的方式做事吗?有没有更简单的方法来获得我想要的结果?

1 个答案:

答案 0 :(得分:2)

不确定为什么你的代码不起作用(也许是一个Json.NET错误?)。相反,您可以从JObject中删除不需要的属性,并在一次调用中写下整个内容:

    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);
    }

或者,您可以创建自己的contract resolver并过滤掉基本属性和成员:

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);