如何将集合(带有索引器属性)序列化为字典 [英] How to serialize a collection (with an indexer property) as a dictionary
问题描述
我有一个类,例如FooCollection
,它实现了IEnumerable<Foo>
,还提供了一个索引器,通过它可以按名称查找Foo
.从功能上讲,它作为字典是只读的.但这并不是真正的字典,因为用户无法决定按键.
I have a class, FooCollection
let's say, which implements IEnumerable<Foo>
, and also provides an indexer by which one can look up a Foo
by its name. Functionally it's read-only as a dictionary. But it's not really a dictionary because users do not get to decide on the keys.
无论如何,我希望JSON.NET将此对象序列化为JSON字典,而不是作为数组进行序列化,它现在正在这样做.在其上粘贴JsonDictionaryAttribute
无效:然后它什么也没做.
Anyway, I want JSON.NET to serialize this object as a JSON dictionary, instead of as an array, which it's doing now. Sticking JsonDictionaryAttribute
on it doesn't work: then it does nothing.
线索?
推荐答案
You're probably going to need to create a custom JsonConverter
for your FooCollection
class in order to serialize it the way you want. Since you haven't posted any code at all, I'll just make something up for sake of example. Let's say your Foo
and FooCollection
classes look like this:
class Foo
{
public int Id { get; set; }
public string Name { get; set; }
}
class FooCollection : IEnumerable<Foo>
{
private List<Foo> list = new List<Foo>();
public void Add(Foo foo)
{
list.Add(foo);
}
public Foo this[string name]
{
get { return list.Find(f => f.Name == name); }
}
public IEnumerator<Foo> GetEnumerator()
{
return list.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)list).GetEnumerator();
}
}
下面的转换器将序列化FooCollection
,就好像它是一个字典一样.我假设您希望转换器将Name
属性的值用作每个Foo
的键,以进行序列化(以匹配集合上的索引器),所以这就是我实现它的方式.您可以通过修改GetFooKey()
方法将其更改为其他内容.
The following converter would serialize the FooCollection
as if it were a dictionary. I'm assuming that you would want the converter to use the value of the Name
property as the key for each Foo
for purposes of serialization (to match the indexer on the collection), so that is how I implemented it. You can change it to something else by modifying the GetFooKey()
method.
class FooCollectionConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(FooCollection));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
writer.WriteStartObject();
foreach (Foo foo in (FooCollection)value)
{
writer.WritePropertyName(GetFooKey(foo));
serializer.Serialize(writer, foo);
}
writer.WriteEndObject();
}
// Given a Foo, return its unique key to be used during serialization
private string GetFooKey(Foo foo)
{
return foo.Name;
}
public override bool CanRead
{
get { return false; }
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
这是一个示例程序,演示了如何使用转换器.
Here is an example program that demonstrates how to use the converter.
class Program
{
static void Main(string[] args)
{
FooCollection coll = new FooCollection();
coll.Add(new Foo { Id = 1, Name = "Moe" });
coll.Add(new Foo { Id = 2, Name = "Larry" });
coll.Add(new Foo { Id = 3, Name = "Curly" });
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new FooCollectionConverter());
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
string json = JsonConvert.SerializeObject(coll, settings);
Console.WriteLine(json);
}
}
这是上面程序的输出:
{
"Moe": {
"Id": 1,
"Name": "Moe"
},
"Larry": {
"Id": 2,
"Name": "Larry"
},
"Curly": {
"Id": 3,
"Name": "Curly"
}
}
提琴: https://dotnetfiddle.net/wI2iQG
这篇关于如何将集合(带有索引器属性)序列化为字典的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!