【问题标题】:Serialize only derived type using Newtonsoft Json.NET仅使用 Newtonsoft Json.NET 序列化派生类型
【发布时间】:2019-06-14 00:30:57
【问题描述】:

是否有任何 JsonSerializerSettings 可用于仅序列化派生类型。

例如,考虑我有以下两个班级。当我序列化 Employee 对象时,结果 json 应该只包含雇员的属性而不是人员类。

public class Person
{
    public string Name { get; set; }
}

public class Employee : Person
{
    public DateTime JoiningDate { get; set; }
    public string EmployeeId { get; set;}
}

【问题讨论】:

  • 在序列化Person 的子类型时是否总是希望Name 被忽略?如果是这样,只需一个简单的忽略属性就可以解决问题。
  • 这只是我给出的一个例子。但我真正的基类有多个属性和深入的对象图。所以只是不想序列化任何基类属性。
  • 按照 mason 的建议,使用 JsonIgnore 属性标记基类中的属性。这应该可以解决问题。
  • 如果仍然存在您可能希望序列化 Person(或任何子类型)具有基类属性的情况,则忽略属性将不起作用。我认为通过创建一个数据传输对象然后对其进行序列化会更好。也许使用AutoMapper 之类的东西从您的 Employee 对象转到您的 DTO。

标签: c# json.net


【解决方案1】:

这样的问题通常反映了模型设计的问题,但是,做你想做的事情的一种方法是摆脱继承;您可以尝试将对象转换为动态对象,然后序列化动态对象:

class MyJson
{
    public static string SerializeObject<T>(T obj, bool ignoreBase)
    {
        if (!ignoreBase)
        {
            return JsonConvert.SerializeObject(obj);
        }

        var myType = typeof(T);
        var props = myType.GetProperties().Where(p => p.DeclaringType == myType).ToList();

        var x = new ExpandoObject() as IDictionary<string, Object>;
        props.ForEach(p => x.Add(p.Name, p.GetValue(obj, null)));

        return JsonConvert.SerializeObject(x);
    }
}

这样称呼

MyJson.SerializeObject<Employee>(e, true)

这样,您可以将它用于任何类型并过滤属性以在帮助器类中进行序列化。例如,您可以检查属性属性并决定是否应将其添加到动态对象中。

【讨论】:

  • 不,有时它仅与对象在内存中的存储方式有关,例如,如果您有一个 ObjectA : BaseA 如果您以将 BaseA 作为参数的方法发送 ObjectA ,例如: DoSomething(BaseA参数)当您序列化参数时,您将序列化所有 objectA 属性,这很棘手,因为有时您不希望这样做。
【解决方案2】:

您可以为此目的使用自定义JsonConverter。请参阅下面的基本版本以供您使用。

public class PersonConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        if (objectType == typeof(Employee))
            return true;

        return false;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        return "";
    }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        JToken t = JToken.FromObject(value);

        if (t.Type != JTokenType.Object)
        {
            t.WriteTo(writer);
        }
        else
        {
            JObject o = (JObject)t;

            o.Remove("Name"); //currently the property name is hardcoded. You could enhance this to remove any property you like

            o.WriteTo(writer);
        }
    }
}

创建JsonConverter 后,您可以在反序列化过程中使用它,如下所示,

var des = JsonConvert.SerializeObject(e, new PersonConverter());
//e is the Person instance we want to convert and PersonConverter is the custom converter
//we use of serialization

请查看link了解更多信息

【讨论】:

  • 谢谢。这是一个很好的解决方案。但仍然在想比这更简单的事情。
  • 谢谢!您在上面的代码中唯一需要调整的是要找到需要删除的属性名称的方式。根据您的要求,您必须决定配置属性名称的最佳方法。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-09-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-10
相关资源
最近更新 更多