Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Add support for serializing types that implement IDictionary<string, object>#38512

Merged
layomia merged 7 commits into
dotnet:masterfrom
layomia:idictionaryobject
Jun 16, 2019
Merged

Add support for serializing types that implement IDictionary<string, object>#38512
layomia merged 7 commits into
dotnet:masterfrom
layomia:idictionaryobject

Conversation

@layomia

@layomia layomia commented Jun 13, 2019

Copy link
Copy Markdown
Contributor

This fixes https://github.com/dotnet/corefx/issues/38372. cc @davidfowl @MarcoRossignoli

public static void ImplementsIDictionaryOfObject()
{
    var input = new StringToObjectIDictionaryWrapper(new Dictionary<string, object>
    {
        { "Name", "David" },
        { "Age", 32 }
    });

    string json = JsonSerializer.ToString(input, typeof(IDictionary<string, object>));
    Assert.Equal(@"{""Name"":""David"",""Age"":32}", json); // Assertion passes.
}

public class StringToObjectIDictionaryWrapper : IDictionary<string, object>
{
    private readonly IDictionary<string, object> _dict;

    public StringToObjectIDictionaryWrapper(IDictionary<string, object> dict)
    {
        _dict = dict;
    }

    public object this[string key] { get => _dict[key]; set => _dict[key] = value; }

    public ICollection<string> Keys => _dict.Keys;

    public ICollection<object> Values => _dict.Values;

    public int Count => _dict.Count;

    public bool IsReadOnly => false;

    public void Add(string key, object value)
    {
        _dict.Add(key, value);
    }

    public void Add(KeyValuePair<string, object> item)
    {
        _dict.Add(item.Key, item.Value);
    }

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

    public bool Contains(KeyValuePair<string, object> item)
    {
        return _dict.Contains(item);
    }

    public bool ContainsKey(string key)
    {
        return _dict.ContainsKey(key);
    }

    public void CopyTo(KeyValuePair<string, object>[] array, int arrayIndex)
    {
        _dict.CopyTo(array, arrayIndex);
    }

    public IEnumerator<KeyValuePair<string, object>> GetEnumerator()
    {
        return _dict.GetEnumerator();
    }

    public bool Remove(string key)
    {
        return _dict.Remove(key);
    }

    public bool Remove(KeyValuePair<string, object> item)
    {
        return _dict.Remove(item);
    }

    public bool TryGetValue(string key, out object value)
    {
        return _dict.TryGetValue(key, out value);
    }

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

To-do: Extend support such that we don't have to indicate the implemented type (https://github.com/dotnet/corefx/issues/38521) i.e

public static void ImplementsIDictionaryOfObject()
{
    var input = new StringToObjectIDictionaryWrapper(new Dictionary<string, object>
    {
        { "Name", "David" },
        { "Age", 32 }
    });

    string json = JsonSerializer.ToString(input); // Type not indicated.
    Assert.Equal(@"{""Name"":""David"",""Age"":32}", json); // Assertion passes.
}

This PR also adds support for (de)serializing IDictionary<string, object>.

Comment thread src/System.Text.Json/tests/Serialization/DictionaryTests.cs
Comment thread src/System.Text.Json/tests/Serialization/DictionaryTests.cs
@layomia layomia self-assigned this Jun 13, 2019
@layomia layomia added this to the 3.0 milestone Jun 13, 2019

@JeremyKuhne JeremyKuhne left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Just a nit, otherwise looks good.

@steveharter steveharter left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

One comment around the original code - please look at history and see why that code was added to make sure we don't break something else. Thanks

@layomia

layomia commented Jun 14, 2019

Copy link
Copy Markdown
Contributor Author

One comment around the original code - please look at history and see why that code was added to make sure we don't break something else. Thanks

See https://github.com/dotnet/corefx/pull/37300/files#r280149022.
It's preventing an attempt to (de)serialize object types. Now that JsonElement is in, we can lift this guard as we need to get a concrete type for IDictionary<string, object> (-> Dictionary<string, object>)

@layomia layomia merged commit e2e5fb2 into dotnet:master Jun 16, 2019
public static void DictionaryOfObject()
{
{
IDictionary obj = JsonSerializer.Parse<IDictionary>(@"{""Key1"":1}");

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why remove the IDictionary test case rather than just adding the Dictionary<string, object> one?

picenka21 pushed a commit to picenka21/runtime that referenced this pull request Feb 18, 2022
…object> (dotnet/corefx#38512)

* Add support for serializing types that implement IDictionary<string, object>

* Add test for string to string IDictionary

* fixup

* Address review feedback

* Rename dict -> dictionary


Commit migrated from dotnet/corefx@e2e5fb2
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

JsonSerializer cannot serialize types that implement IDictionary<string, object>

6 participants