2020年9月13日星期日

继承自ListT的类通过NewtonJson的序列化问题

啥问题呀?

NewtonSoft.Json是我们最常用的Json组件库之一了。这里来讨论下使用NewtonSoft.Json序列化List<T>子类的情景。序列化使用了类JsonSerializer

情景重现

如果我们有一个Field实体类。另有一个FieldGroup类表示Field的分组,并携带组属性GroupFormat。我们需要序列化这个FieldGroup,该如何实现呢?

机智如我,这么写了:

// FieldGroup 实现类public class FieldGroup : List<Field>{ public Format GroupFormat{ get;set; }}// 序列化过程public void main(){ var group = new FieldGroup() {  GroupFormat = "Format 1" }; group.Add(new Field() {  Name = "Field 1" }); Console.WriteLine(JsonUtil.SerializeByNsj(group));}

结果我很纳闷儿,GroupFormat属性被JsonSerializer吃了吗?

[ {  "Name": "Field 1" }]

咋解决呢?

既然JsonSerializer不会自己处理这个GroupFormat属性,那我来告诉你它是必须要序列化的!我们使用[JsonObject(MemberSerialization.OptOut)]来标记这个类除了显示地标记了[JsonIgnore]特性的公有属性都需要被序列化。

[JsonObject(MemberSerialization.OptOut)]public class FieldGroup : List<Field>{ public string Format { get; set; }}

这下好了吧?emmmmmmm......

{ "Format": "Format 1", "Capacity": 4, "Count": 1}

神(NewtonSoft.Json)呐!你又把List吃了吗!我该拿你怎样昂昂昂昂昂昂......
当然是,这样:

[JsonObject(MemberSerialization.OptOut)]public class FieldGroup : IEnumerable<Field>{ public PrintFormat GroupFormat { get; set; } = new PrintFormat(); // 使用内部的 List<Field> 代替继承,可直接被序列化和反序列化 public List<Field> Fields { get; set; } = new List<Field>(); // 使用索引对外提供类似于List<T>的访问方式; public Field this[int index] {  get => Fields[index];  set => Fields[index] = value; } // 提供List<T>一致的Add方法,有需要可以提供其他方法 public void Add(Field field) {  Fields.Add(field); } // 提供类似于List<T>的IEnumerable功能 public IEnumerator<Field> GetEnumerator() {  return new FieldEnumerator(Fields); } IEnumerator IEnumerable.GetEnumerator() {  return GetEnumerator(); }}

这次的结果是?

{ "Fields": [  {   "Name": "Field 1"  } ], "Format": "Format 1"}

老外有话说

Is there any way to JSON.NET-serialize a subclass of List that also has extra properties?

public class LocationListJsonConverter : JsonConverter{ public override bool CanConvert(System.Type objectType) {  return objectType == typeof(LocationList); } public override object ReadJson(JsonReader reader, System.Type objectType, object existingValue, JsonSerializer serializer) {  var locationList = (existingValue as LocationList) ?? new LocationList();  var jLocationList = JObject.ReadFrom(reader);  locationList.IsExpanded = (bool)(jLocationList["IsExpanded"] ?? false);  var jLocations = jLocationList["_Items"];  if(jLocations != null)  {   foreach(var jLocation in jLocations)   {    var location = serializer.Deserialize<Location>(new JTokenReader(jLocation));    locationList.Add(location);   }  }  return locationList; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) {  var locationList = value as LocationList;  JObject jLocationList = new JObject();  if(locationList.IsExpanded)   jLocationList.Add("IsExpanded", true);  if(locationList.Count > 0)  {   var jLocations = new JArray();   foreach(var location in locationList)   {    jLocations.Add(JObject.FromObject(location, serializer));   }   jLocationList.Add("_Items", jLocations);  }  jLocationList.WriteTo(writer); }}

我的博客园:https://www.cnblogs.com/liwuqingxin/

我的个人站:https://liwuqingxin.github.io/

继承自ListT的类通过NewtonJson的序列化问题easybuy亚马逊全球开店从0到1新手入门实操课焦点科技亚马逊选品系列:如何研究目标产品的细分市场?脑壳疼?2019旺季清库存,赶紧查收这份清库存秘籍!MangaToon亚马逊新卖家如何选品?选品方法分享致亚马逊小白卖家-2019亚马逊运营原来还能这样操作!

没有评论:

发表评论