【问题标题】:Deserialize to custom list [duplicate]反序列化为自定义列表[重复]
【发布时间】:2015-11-03 11:11:08
【问题描述】:

出于性能原因,我创建了一个自定义 List 类,该类维护一组项目 ID:

public class MyCustomList : List<ItemWithID>
{
    private HashSet<int> itemIDs = new HashSet<int>();

    public MyCustomList()
    {
    }

    [JsonConstructor]
    public MyCustomList(IEnumerable<ItemWithID> collection)
        : base(collection)
    {
        itemIDs = new HashSet<int>(this.Select(i => i.ID));
    }

    public new void Add(ItemWithID item)
    {
        base.Add(item);
        itemIDs.Add(item.ID);
    }

    public new bool Remove(ItemWithID   item)
    {
        var removed = base.Remove(item);
        if (removed)
        {
            itemIDs.Remove(item.ID);
        }
        return removed;
    }

    public bool ContainsID(int id)
    {
        return itemIDs.Contains(id);
    }
}

我想从一个简单的 JSON 数组中反序列化这个 List,例如:

JsonConvert.DeserializeObject<MyCustomList>("[{ID:8},{ID:9}]");

这将导致 JSON.NET 仅调用空构造函数,因此我的 itemIDs 列表保持为空。也不会调用 Add 方法。

JSON.NET 如何将项目添加到列表中,以便我可以在该位置添加逻辑。

(这是关于反序列化没有应该在json字符串中持久存在的属性,所以建议的重复问题与这个无关)

【问题讨论】:

  • 不是重复的(见更新的问题)
  • 您的问题不在于 JSON 反序列化,如果您希望能够覆盖 Add 方法,您的 MyCustomList 需要从 IList 派生。详情请见THIS
  • @Meehow 谢谢,现在我明白了 new 和 override 之间的区别。将此作为答案,我会接受。
  • 亲爱的@jan-s,您不喜欢我的答案吗?因为您将 45 分钟后发布的另一个答案标记为答案,其中包含实际工作代码?
  • @OguzOzgul 是的,你的答案是一个解决方案,但我错过了一个解释。

标签: c# json inheritance json.net


【解决方案1】:

解决方案:

public class MyCustomList : IList<ItemWithID>
{
    private HashSet<int> itemIDs = new HashSet<int>();
    private List<ItemWithID> actualList = new List<ItemWithID>();

    public void Add(ItemWithID item)
    {
        actualList.Add(item);
        itemIDs.Add(item.ID);
    }

    public bool Remove(ItemWithID item)
    {
        var removed = actualList.Remove(item);
        if (removed)
        {
            itemIDs.Remove(item.ID);
        }
        return removed;
    }

    public bool ContainsID(int id)
    {
        return itemIDs.Contains(id);
    }

    public int IndexOf(ItemWithID item)
    {
        return actualList.IndexOf(item);
    }

    public void Insert(int index, ItemWithID item)
    {
        actualList.Insert(index, item);
        itemIDs.Add(item.ID);
    }

    public void RemoveAt(int index)
    {
        itemIDs.Remove(actualList[index].ID);
        actualList.RemoveAt(index);

    }

    public ItemWithID this[int index]
    {
        get
        {
            return actualList[index];
        }
        set
        {
            actualList[index] = value;
            if (!itemIDs.Contains(value.ID))
            {
                itemIDs.Add(value.ID);
            }
        }
    }

    public void Clear()
    {
        actualList.Clear();
        itemIDs.Clear();
    }

    public bool Contains(ItemWithID item)
    {
        return actualList.Contains(item);
    }

    public void CopyTo(ItemWithID[] array, int arrayIndex)
    {
        actualList.CopyTo(array, arrayIndex);
    }

    public int Count
    {
        get { return actualList.Count; }
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public IEnumerator<ItemWithID> GetEnumerator()
    {
        return actualList.GetEnumerator();
    }

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

【讨论】:

    【解决方案2】:

    您可以反序列化为构造函数期望的形式,然后自己调用它。

    var collection = JsonConvert.DeserializeObject<ItemID[]>("[{ID:8},{ID:9}]");
    
    var aCustomList = new MyCustomList(collection);
    

    【讨论】:

    • 请问除了分成两行之外,这与当前的实现有何不同?
    • 唯一的缺点是当 MyCustomList 被另一方反序列化(例如 WebAPI)时,项目 id 列表将再次为空。
    • @Meehow 不同之处在于 JsonConvert 反序列化为的类型。此外,然后使用其结果调用所需的构造函数。在原始代码中调用了空构造函数。
    • @OguzOzgul 正是问题所在。反序列化示例被简化,而不是真正的用例
    【解决方案3】:

    您的问题不在于 JSON 反序列化,如果您希望能够覆盖 Add 方法,您的 MyCustomList 类需要从 IList 派生。详情请见THIS

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-05-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多