如何将集合(带有索引器属性)序列化为字典 [英] How to serialize a collection (with an indexer property) as a dictionary

查看:76
本文介绍了如何将集合(带有索引器属性)序列化为字典的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个类,例如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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆