反序列化为自定义列表

时间:2015-11-03 11:11:09

标签: c# json inheritance json.net

我创建了一个自定义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仅调用空构造函数,因此我的itemID列表仍为空。此外,不会调用Add方法。

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

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

3 个答案:

答案 0 :(得分:4)

解决方案:

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();
    }
}

答案 1 :(得分:3)

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

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

var aCustomList = new MyCustomList(collection);

答案 2 :(得分:1)

您的问题不在于JSON反序列化,如果您希望能够覆盖MyCustomList方法,则IList类需要从Add派生。有关详细信息,请参阅THIS