当前位置: 首页 > 面试题库 >

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

茅华灿
2023-03-14
问题内容

我正在尝试仅使用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(writer);
它给出的结果与不使用转换器的结果相同。当遍历属性并在属性上使用WriteTo时,它对于基本类型(int,字符串等)正常工作,但是集合存在问题。

预期:

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

得到:

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

如您所见,该集合缺少“,”和结束行部分。我也缺少整个对象的全局{}。

我在做正确的事情吗?有没有更简单的html" target="_blank">方法来获得我想要的结果?


问题答案:

不知道为什么您的代码不起作用(可能是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);
    }

另外,您可以创建自己的合同解析器并过滤基本属性和成员:

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


 类似资料:
  • 我面临一个生成器类继承的序列化问题。如下所示: 基类: 我看到以下例外: 有人知道如何避免这个问题吗?

  • 在Android应用程序中,我需要用一个抽象级别反序列化Kotlin数据类的Json数据。但我不知道如何在构造函数中放置正确的属性。 简单来说,假设我有一个形状: 有两个派生 和 所以我的目标是,不要实例化一个形状。所以,相反,总是反序列化它的派生。稍后,我需要处理其他类中的一些集合属性,如: 但我还必须知道每个元素的派生类型。 当我尝试用Gson反序列化给定的示例时 我总是有一个非法的辩论例外

  • 问题内容: 我希望能够在使用System.Text.Json.JsonSerializer进行序列化时排除属性。我不想在每个我想做的地方都使用属性。我希望能够通过某种Fluent API定义仅在序列化过程中要排除的属性,目前尚不存在。 我能够找到的唯一选择是定义一个,并将其添加到我传递给Serialize()方法的的Converters列表中,如下所示: 在JsonConverter中,我必须使用

  • 问题内容: 我有一个模型如下: 我从返回: 当我检查JSON结果时,它确实包含所有,但是(和)上的属性不可见。 如何将这些值也包含在JSON序列化的对象中? 我尝试使用属性来装饰属性,但没有成功。 问题答案: 您的基本困难是JSON有两种类型的容器:对象和数组。从标准: 数组是值的有序集合。数组以(左括号)开始,以(右括号)结束。值之间用(逗号)分隔。 对象是名称/值对的无序集合。对象以(左大括号

  • 我有一个简单的Json结构,比如: 我设计了以下类来反序列化它: 我需要将反序列化分为两个阶段: 1-反序列化以读取。 2.2基于MessageType进行其余的反序列化 代码很简单: 我的程序可以输入正确的(即),但它不能正确解析它(println打印0而不是12) 你觉得我哪里做错了?谢谢你们

  • 问题:类A实现可序列化类B扩展了类A实现可序列化 现在我只使用类B作为运行时类型进行序列化。所以我有一个列表: 如果我现在反序列化它,我就得到了java。伊奥。OptionalDataException错误。我想知道的是,我的对象如何成为正确的运行时类型。反序列化: 如果在序列化时是类B的运行时类型,这是否会导致类B的运行时类型,或者我必须覆盖A的earch子类的默认序列化? 希望我没有错过任何明