Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support (de)serializing types that implement IDictionary and IDictionary<string, TValue> without hint of implemented type #29870

Closed
layomia opened this issue Jun 13, 2019 · 4 comments · Fixed by dotnet/corefx#39001
Assignees
Labels
area-System.Text.Json json-functionality-doc Missing JSON specific functionality that needs documenting
Milestone

Comments

@layomia
Copy link
Contributor

layomia commented Jun 13, 2019

e.g. Given

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

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

    // Implementation for IDictionary<string, object>
    ...
}

After dotnet/corefx#38512 is merged, this will work:

[Fact]
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>)); // Providing implemented type
    Assert.Equal(@"{""Name"":""David"",""Age"":32}", json);

    IDictionary<string, object> obj = JsonSerializer.Parse<IDictionary<string, object>>(json); // Parsing to implemented type
    Assert.Equal(2, obj.Count);
    Assert.Equal("David", ((JsonElement)obj["Name"]).GetString());
    Assert.Equal(32, ((JsonElement)obj["Age"]).GetInt32());
}

This doesn't work

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

    // This throws NotSupportedException
    string json = JsonSerializer.ToString(input); // Not providing implemented type
    Assert.Equal(@"{""Name"":""David"",""Age"":32}", json);

    // (Assuming json == @"{""Name"":""David"",""Age"":32}") This throws NotSupportedException
    StringToObjectIDictionaryWrapper obj = JsonSerializer.Parse<StringToObjectIDictionaryWrapper>(json); // Parsing to actual type
    Assert.Equal(2, obj.Count);
    Assert.Equal("David", ((JsonElement)obj["Name"]).GetString());
    Assert.Equal(32, ((JsonElement)obj["Age"]).GetInt32());
}
@ahsonkhan
Copy link
Contributor

@steveharter, can you please take a look and see if this issue is something we should be fixing, or is by design.

@steveharter
Copy link
Member

{ "Name", "David" } is not a valid way to represent a dictionary entry, @layomia we don't support this currently, do we?

Only name:value pairs like this { "Name" :"David" } and perhaps { "Key":"Name", "Value":"David" }

@layomia
Copy link
Contributor Author

layomia commented Jun 19, 2019

{ "Name", "David" } is not a valid way to represent a dictionary entry, @layomia we don't support this currently, do we?

Only name:value pairs like this { "Name" :"David" } and perhaps { "Key":"Name", "Value":"David" }

@steveharter this code is creating a new instance of the StringToObjectIDictionaryWrapper type which implements IDictionary<string, object>.

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

The question is should we be able to parse the json string @"{""Name"":""David"",""Age"":32}" to a StringToObjectIDictionaryWrapper type (and roundtrip i.e. serialize back to the json string) since it implements IDictionary<string, object>?

Same question would apply to types that implement any of the interfaces we support - ICollection, IList<T>, etc.

@steveharter
Copy link
Member

I see. Yes we should deserialize "David" and 32 both into a JsonElement, like we do for other "object" cases in dictionaries.

@steveharter steveharter assigned layomia and unassigned steveharter Jun 19, 2019
@msftgits msftgits transferred this issue from dotnet/corefx Feb 1, 2020
@msftgits msftgits added this to the 3.0 milestone Feb 1, 2020
@ghost ghost locked as resolved and limited conversation to collaborators Dec 12, 2020
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Text.Json json-functionality-doc Missing JSON specific functionality that needs documenting
Projects
None yet
Development

Successfully merging a pull request may close this issue.

4 participants