Skip to content

Struct properties that implement IList<T> are unable to hold values on Deserialization #1998

Description

@jozkee

Properties of a custom struct type that implements IList<T> are unable to read values, this is because when we try to add the element into the list, we do it on a copy of said property which is returned by jsonPropertyInfo.GetValueAsObject(state.Current.ReturnValue).

This issue is probably duplicated also on custom structs that implement Dictionary or IDictionary.
This issue does not occur when the value type list is the root object.

I would wait to see if the new converter refactor indirectly fixes this issue.
cc @steveharter, @layomia, @ahsonkhan

Repro:

[Fact]
public static void StructListPropertyDoesNotHoldElements()
{
    string json = $"{{\"StructList\":[10,20,30,40,50,60,70,80]}}";
    StructListWrapper wrapper = JsonSerializer.Deserialize<StructListWrapper>(json);
    Assert.Equal(8, wrapper.StructList.Count);
}

private class StructListWrapper
{
    public StructList<int> StructList { get; set; }
}

private struct StructList<T> : IList<T>
{
    private List<T> _list;
    public T this[int index]
    {
        get {
            InitializeIfNull();
            return _list[index];
        }
        set {
            InitializeIfNull();
            _list[index] = value;
        }
    }

    public int Count => _list == null? 0: _list.Count;

    public bool IsReadOnly => false;

    private void InitializeIfNull()
    {
        if (_list == null) {
            _list = new List<T>();
        }
    }

    public void Add(T item)
    {
        InitializeIfNull();
        _list.Add(item);
    }

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

    public bool Contains(T item)
    {
        return _list.Contains(item);
    }

    public void CopyTo(T[] array, int arrayIndex)
    {
        throw new NotImplementedException();
    }

    public IEnumerator<T> GetEnumerator()
    {
        return _list.GetEnumerator();
    }

    public int IndexOf(T item)
    {
        return _list.IndexOf(item);
    }

    public void Insert(int index, T item)
    {
        _list.Insert(index, item);
    }

    public bool Remove(T item)
    {
        return _list.Remove(item);
    }

    public void RemoveAt(int index)
    {
        _list.RemoveAt(index);
    }

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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions