【问题标题】:C# - Json.NET - Serialization with inheritanceC# - Json.NET - 具有继承的序列化
【发布时间】:2015-06-16 10:15:41
【问题描述】:

我有这门课:

using Sierra.Collections;

namespace Sierra
{
    public sealed class Worlds : SafeKeyedCollection<byte, World>
    {
        public Worlds() : base() { }

        protected override byte GetKeyForItem(World item)
        {
            return item.Id;
        }
    }
}

世界级:

using Sierra.Collections;

namespace Sierra
{
    public sealed class World : SafeKeyedCollection<byte, Channel>
    {
        public byte Id { get; set; }
        public string Name { get; set; }
        public ushort Port { get; set; }
        public ushort ShopPort { get; set; }
        public ushort MonsterLifePort { get; set; }
        public ushort TalkPort { get; set; }
        public byte Ribbon { get; set; }
        public byte Channels { get; set; }
        public string EventMessage { get; set; }
        public string ScrollingHeader { get; set; }
        public bool AllowMultiLeveling { get; set; }
        public int DefaultCreationSlots { get; set; }
        public bool DisableCharacterCreation { get; set; }

        public World() : base() { }

        protected override byte GetKeyForItem(Channel item)
        {
            return item.Id;
        }
    }
}

当我是 Worlds 对象时,它不会序列化它。该列表似乎是空的:

public Worlds Worlds { get; set; }

它输出:

"Worlds": [
    []
]

这是为什么呢?你不能序列化一个继承自另一个类的类吗?

SafeKeyedCollection

    using System;
using System.Collections;
using System.Collections.Generic;

namespace Sierra.Collections
{
    /// <summary>
    /// Thread safe NumericalKeyedCollection class - Patel
    /// Soooooooooooooo fire
    /// </summary>
    public abstract class SafeKeyedCollection<TKey, TItem> : IEnumerable<TItem>
    {
        private Object m_Lock;
        private Dictionary<TKey, TItem> m_Inner;

        public SafeKeyedCollection()
        {
            m_Lock = new object();
            m_Inner = new Dictionary<TKey, TItem>();
        }

        public int Count
        {
            get
            {
                lock (m_Lock)
                {
                    return m_Inner.Count;
                }
            }
        }

        public TItem this[TKey key]
        {
            get
            {
                lock (m_Lock)
                {
                    TItem ret;

                    m_Inner.TryGetValue(key, out ret);

                    return ret;
                }
            }
        }

        public void Add(TItem item)
        {
            this.InsertItem(item);
        }

        public void Remove(TItem item)
        {
            this.RemoveItem(item);
        }

        protected virtual void InsertItem(TItem item)
        {
            lock (m_Lock)
            {
                TKey key = GetKeyForItem(item);
                m_Inner.Add(key, item);

            }
        }
        protected virtual void RemoveItem(TItem item)
        {
            lock (m_Lock)
            {
                TKey key = GetKeyForItem(item);
                m_Inner.Remove(key);
            }
        }
        public void Clear()
        {
            lock (m_Lock)
            {
                m_Inner.Clear();
            }
        }
        public bool Contains(TKey key)
        {
            lock (m_Lock)
            {
                return m_Inner.ContainsKey(key);
            }
        }
        public bool Contains(TItem value)
        {
            lock (m_Lock)
            {
                return m_Inner.ContainsValue(value);
            }
        }

        protected abstract TKey GetKeyForItem(TItem item);

        protected virtual void ClearItems() { }

        public IEnumerator<TItem> GetEnumerator()
        {
            return new SafeEnumerator<TItem>(() => m_Inner.Values.GetEnumerator(), m_Lock);
        }
        IEnumerator IEnumerable.GetEnumerator()
        {
            return GetEnumerator();
        }
    }
}

谢谢

【问题讨论】:

    标签: c# json


    【解决方案1】:

    基本问题是您正在尝试序列化已被子类化以包含自定义属性的集合(此处为SafeKeyedCollection&lt;TKey, TItem&gt; : IEnumerable&lt;TItem&gt;)。这无法做到,因为JSON standard 只定义了两种类型的容器:

    1. 具有命名键/值属性的对象:{"a": 1, "b" : "two" }
    2. 元素数组:[1, 2, 3, {"a": 1}]

    没有容器可以同时具有 命名属性和任意数量的未命名元素——在序列化中,项目或属性必须优先。事实上,所有 JSON 序列化程序都选择将任何实现 IEnumerable 的东西默认序列化为数组,省略属性。这就是你所看到的。您一般可以序列化从另一个类继承的类,而不是子类集合的可设置属性。

    如何处理?微软的Guidelines for Collections 状态

    避免在具有与集合概念无关的复杂 API 的类型上实现集合接口。

    因此您可能会考虑更改您的数据模型(这也会导致XmlSerializer 出现问题)以将集合包含在某个更高的对象中,而不是子类中。

    如果您希望保留当前的数据模型,那么可用的解决方法取决于您使用的序列化程序:

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2014-01-06
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 2012-09-05
      • 2012-11-28
      • 2012-12-20
      • 1970-01-01
      相关资源
      最近更新 更多