我有一个自定义集合(实现IList),它具有一些自定义属性,如下所示:
class FooCollection : IList<Foo> { private List<Foo> _foos = new List<Foo>(); public string Bar { get; set; } //Implement IList, ICollection and IEnumerable members... }
序列化时,使用以下代码:
JsonSerializerSettings jss = new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.Auto }; string serializedCollection = JsonConvert.SerializeObject( value , jss );
它正确地序列化和反序列化所有收集项;但是,FooCollection不会考虑该类中的任何其他属性。
FooCollection
无论如何,有没有将它们包括在序列化中?
问题如下:当对象实现时IEnumerable,JSON.net将其标识为值数组,并按照数组Json语法(不包括属性)对其进行序列化,例如:
IEnumerable
[ {"FooProperty" : 123}, {"FooProperty" : 456}, {"FooProperty" : 789}]
如果要序列化它保留属性,则需要通过定义一个custom来手工处理该对象的序列化JsonConverter:
JsonConverter
// intermediate class that can be serialized by JSON.net // and contains the same data as FooCollection class FooCollectionSurrogate { // the collection of foo elements public List<Foo> Collection { get; set; } // the properties of FooCollection to serialize public string Bar { get; set; } } public class FooCollectionConverter : JsonConverter { public override bool CanConvert(Type objectType) { return objectType == typeof(FooCollection); } public override object ReadJson( JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { // N.B. null handling is missing var surrogate = serializer.Deserialize<FooCollectionSurrogate>(reader); var fooElements = surrogate.Collection; var fooColl = new FooCollection { Bar = surrogate.Bar }; foreach (var el in fooElements) fooColl.Add(el); return fooColl; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { // N.B. null handling is missing var fooColl = (FooCollection)value; // create the surrogate and serialize it instead // of the collection itself var surrogate = new FooCollectionSurrogate() { Collection = fooColl.ToList(), Bar = fooColl.Bar }; serializer.Serialize(writer, surrogate); } }
然后按以下方式使用它:
var ss = JsonConvert.SerializeObject(collection, new FooCollectionConverter()); var obj = JsonConvert.DeserializeObject<FooCollection>(ss, new FooCollectionConverter());