NewtonSoft.Json是咱們最經常使用的Json組件庫之一了。這裏來討論下使用NewtonSoft.Json序列化List<T>子類的情景。序列化使用了類JsonSerializer。git
若是咱們有一個Field實體類。另有一個FieldGroup類表示Field的分組,並攜帶組屬性GroupFormat。咱們須要序列化這個FieldGroup,該如何實現呢?github
機智如我,這麼寫了:json
// 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吃了嗎?ide
[ { "Name": "Field 1" } ]
既然JsonSerializer不會本身處理這個GroupFormat屬性,那我來告訴你它是必需要序列化的!咱們使用[JsonObject(MemberSerialization.OptOut)]來標記這個類除了顯示地標記了[JsonIgnore]特性的公有屬性都須要被序列化。this
[JsonObject(MemberSerialization.OptOut)] public class FieldGroup : List<Field> { public string Format { get; set; } }
這下好了吧?emmmmmmm......3d
{ "Format": "Format 1", "Capacity": 4, "Count": 1 }
神(NewtonSoft.Json)吶!你又把List吃了嗎!我該拿你怎樣昂昂昂昂昂昂......
固然是,這樣:code
[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(); } }
此次的結果是?orm
{ "Fields": [ { "Name": "Field 1" } ], "Format": "Format 1" }
Is there any way to JSON.NET-serialize a subclass of List
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); } }