Pie*_* SS 21 .net c# serialization json json.net
我有一个自定义集合(实现IList),它有一些自定义属性,如下所示:
class FooCollection : IList<Foo> {
private List<Foo> _foos = new List<Foo>();
public string Bar { get; set; }
//Implement IList, ICollection and IEnumerable members...
}
Run Code Online (Sandbox Code Playgroud)
当我序列化时,我使用以下代码:
JsonSerializerSettings jss = new JsonSerializerSettings() {
TypeNameHandling = TypeNameHandling.Auto
};
string serializedCollection = JsonConvert.SerializeObject( value , jss );
Run Code Online (Sandbox Code Playgroud)
它正确地序列化和反序列化所有收集项目; 但是,FooCollection
不考虑课堂上的任何额外属性.
无论如何将它们包含在序列化中?
dig*_*All 22
问题如下:当一个对象实现时IEnumerable
,JSON.net将其标识为值数组,并按照数组Json语法(不包括属性)将其序列化,例如:
[ {"FooProperty" : 123}, {"FooProperty" : 456}, {"FooProperty" : 789}]
Run Code Online (Sandbox Code Playgroud)
如果要保留属性的序列化,则需要通过定义自定义来手动处理该对象的序列化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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后使用如下:
var ss = JsonConvert.SerializeObject(collection, new FooCollectionConverter());
var obj = JsonConvert.DeserializeObject<FooCollection>(ss, new FooCollectionConverter());
Run Code Online (Sandbox Code Playgroud)
Jef*_*f E 12
就个人而言,我喜欢尽可能避免编写自定义JsonConverter
s,而是使用为此目的而设计的各种JSON属性.你可以简单的装饰FooCollection
用JsonObjectAttribute
,这迫使系列化的JSON对象,而不是一个数组.您必须装饰Count
和IsReadOnly
属性JsonIgnore
以防止它们出现在输出中.如果你想保留_foos
一个私人领域,你也必须用它来装饰它JsonProperty
.
[JsonObject]
class FooCollection : IList<Foo> {
[JsonProperty]
private List<Foo> _foos = new List<Foo>();
public string Bar { get; set; }
// IList implementation
[JsonIgnore]
public int Count { ... }
[JsonIgnore]
public bool IsReadOnly { ... }
}
Run Code Online (Sandbox Code Playgroud)
序列化产生如下内容:
{
"_foos": [
"foo1",
"foo2"
],
"Bar": "bar"
}
Run Code Online (Sandbox Code Playgroud)
显然,这只有在您能够更改定义FooCollection
以便添加这些属性时才有效,否则您必须采用自定义转换器的方式.
归档时间: |
|
查看次数: |
14087 次 |
最近记录: |