将JSON.NET与OrderedDictionary一起使用

问题描述 投票:1回答:1

我有一个带有OrderedDictionary键和int值的System.Drawing.Rectangle。 JSON.NET不会序列化OrderedDictionary ...它返回一个空对象。我写了一个自定义转换器,但我想知道是否有更简单的方法。考虑到JSON.NET可能使用类型化枚举器作为触发器来使用其内置代码对Dictionary<TKey, TValue>进行序列化和反序列化,因此我尝试了此操作:

class Program
{
    static void Main(string[] args)
    {
        var test = new OrderedDictionary<int, Rectangle>();
        test.Add(1, new Rectangle(0, 0, 50, 50));
        test.Add(42, new Rectangle(1, 1, 1, 1));

        string s = JsonConvert.SerializeObject(test);
        var deserialized = JsonConvert.DeserializeObject<OrderedDictionary<int, Rectangle>>(s);

        var someRect = deserialized[(object)1]; // someRect is null
        var someOtherRect = (Rectangle)deserialized["1"]; // InvalidCastException
    }
}

public class OrderedDictionary<TKey, TValue> : OrderedDictionary, IEnumerable<KeyValuePair<TKey, TValue>>
{
    IEnumerator<KeyValuePair<TKey, TValue>> IEnumerable<KeyValuePair<TKey, TValue>>.GetEnumerator()
    {
        foreach (TKey key in Keys)
        {
            yield return new KeyValuePair<TKey, TValue>(key, (TValue)this[key]);
        }
    }
}

序列化效果很好。但是,当我反序列化时,字典中的键变成字符串,并且Rectangle是无法转换为JObjectRectangle。我可以添加一些到OrderedDictionary<>类中的内容,以允许使用JSON.NET进行适当的反序列化吗?谢谢。

c# json.net ordereddictionary
1个回答
1
投票

您的问题是,尽管您已经添加了枚举器,但无法覆盖索引器之类的东西。因此,您得到的是非通用OrderedDictionary的默认实现,该实现不会为您提供输入结果。

因此,您需要一个完全实现通用接口的外观,而不是继承。

您需要验证我的课程(我刚刚完成了测试工作)。我还欺骗了Keys和Values属性(它们不经常使用)和其他一些ICollection方法。只是懒惰:)

using System;
using System.Collections;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using Newtonsoft.Json;
using Xunit;

namespace XUnitTestProject1
{
    public class UnitTest1
    {
        [Fact]
        public void TestJsonRectange()
        {
            var test = new OrderedDictionary<int, Rectangle>();
            test.Add(1, new Rectangle(0, 0, 50, 50));
            test.Add(42, new Rectangle(1, 1, 1, 1));
            string json = JsonConvert.SerializeObject(test);

            var deserialized = JsonConvert.DeserializeObject<OrderedDictionary<int, Rectangle>>(json);

            object someRect = deserialized[1];
            Assert.NotNull(someRect);
            Assert.True(someRect is Rectangle);
        }
        [Fact]
        public void TestJsonString()
        {
            var test = new OrderedDictionary<string, string>();
            test.Add("1", "11");
            test.Add("42", "4242");
            string json = JsonConvert.SerializeObject(test);

            var deserialized = JsonConvert.DeserializeObject<OrderedDictionary<string, string>>(json);

            object something = deserialized["1"];
            Assert.NotNull(something);
            Assert.True(something is string);
        }

        public class OrderedDictionary<TKey, TValue> : IDictionary<TKey, TValue>
        {
            private readonly OrderedDictionary dic = new OrderedDictionary();

            public TValue this[TKey key] { get { return (TValue)dic[key]; } set { dic[key] = value; } }

            public void Add(KeyValuePair<TKey, TValue> item)
            {
                dic.Add(item.Key, item.Value);
            }
            public void Add(TKey key, TValue value)
            {
                dic.Add(key, value);
            }

            public void Clear() { dic.Clear(); }


            public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) { }


            public int Count { get { return dic.Count; } }
            public bool IsReadOnly { get { return false; } }

            public bool Contains(TKey key) { return dic.Contains(key); }
            public bool ContainsKey(TKey key) { return dic.Contains(key); }

            public bool Remove(TKey key) { dic.Remove(key); return true; }

            public bool TryGetValue(TKey key, out TValue value) { value = default(TValue); return false; }

            bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
            {
                throw new NotImplementedException();
            }
            bool ICollection<KeyValuePair<TKey, TValue>>.Remove(KeyValuePair<TKey, TValue> item) { return false; }

            public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
            {
                foreach (DictionaryEntry entry in dic)
                    yield return new KeyValuePair<TKey, TValue>((TKey)entry.Key, (TValue)entry.Value);
            }

            IEnumerator IEnumerable.GetEnumerator()
            {
                return GetEnumerator();
            }

            private static readonly TKey[] keys = new TKey[0];
            private static readonly TValue[] values = new TValue[0];

            ICollection<TKey> IDictionary<TKey, TValue>.Keys { get { return keys; } }
            ICollection<TValue> IDictionary<TKey, TValue>.Values { get { return values; } }
        }
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.