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

System.Text.Json.JsonSerializer cannot deal with base interfaces #47753

Closed
ramondeklein opened this issue Feb 2, 2021 · 6 comments
Closed

System.Text.Json.JsonSerializer cannot deal with base interfaces #47753

ramondeklein opened this issue Feb 2, 2021 · 6 comments
Labels
area-System.Text.Json untriaged New issue has not been triaged by the area owner

Comments

@ramondeklein
Copy link

Description

It seems that System.Text.Json.JsonSerializer only serializes the properties of the top-level interface, instead of all the underlying interface. Suppose the following code:

public interface IBase
{
    int Count { get; set; }
}

public interface IDerived : IBase
{
    string Name { get; set; }
}

public class Implementation : IDerived
{
    public int Count { get; set; }
    public string Name { get; set; }
}

internal static class Program
{
    private static void Main(string[] args)
    {
        var obj = new Implementation {Count = 1, Name = "Test"};

        // {"Count":1,"Name":"Test"}
        System.Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(obj));

        // {"Name":"Test"}   <-- Count is not serialized, because it's defined in a base interface
        System.Console.WriteLine(System.Text.Json.JsonSerializer.Serialize((IDerived)obj));
    }
}

When serializing the object as IDerived then only the properties that are defined in this interface are exported. I could imagine this behaviour when IDerived wasn't derived from IBase and when Implementation would derive from both base interfaces. But the properties of IDerived should include also the base properties to make sure you can serialize the object appropriately.

I am familiar that the behaviour has changed (compared to the Newtonsoft.Json serializer), but this behaviour is very unexpected and doesn't seem right. The properties of the base interface are part of IDerived and should be serialized. I couldn't think of a reason not to (de)serialize the base properties, but if it's breaking existing code, then please add a property to opt-in for base-property serialization.

@dotnet-issue-labeler dotnet-issue-labeler bot added area-System.Text.Json untriaged New issue has not been triaged by the area owner labels Feb 2, 2021
@ghost
Copy link

ghost commented Feb 2, 2021

Tagging subscribers to this area: @eiriktsarpalis, @layomia
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

It seems that System.Text.Json.JsonSerializer only serializes the properties of the top-level interface, instead of all the underlying interface. Suppose the following code:

public interface IBase
{
    int Count { get; set; }
}

public interface IDerived : IBase
{
    string Name { get; set; }
}

public class Implementation : IDerived
{
    public int Count { get; set; }
    public string Name { get; set; }
}

internal static class Program
{
    private static void Main(string[] args)
    {
        var obj = new Implementation {Count = 1, Name = "Test"};

        // {"Count":1,"Name":"Test"}
        System.Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(obj));

        // {"Name":"Test"}   <-- Count is not serialized, because it's defined in a base interface
        System.Console.WriteLine(System.Text.Json.JsonSerializer.Serialize((IDerived)obj));
    }
}

When serializing the object as IDerived then only the properties that are defined in this interface are exported. I could imagine this behaviour when IDerived wasn't derived from IBase and when Implementation would derive from both base interfaces. But the properties of IDerived should include also the base properties to make sure you can serialize the object appropriately.

I am familiar that the behaviour has changed (compared to the Newtonsoft.Json serializer), but this behaviour is very unexpected and doesn't seem right. The properties of the base interface are part of IDerived and should be serialized. I couldn't think of a reason not to (de)serialize the base properties, but if it's breaking existing code, then please add a property to opt-in for base-property serialization.

Author: ramondeklein
Assignees: -
Labels:

area-System.Text.Json, untriaged

Milestone: -

@Tornhoof
Copy link
Contributor

Tornhoof commented Feb 2, 2021

It seems that System.Text.Json.JsonSerializer only serializes the properties of the top-level interface, instead of all the underlying interface.

This is documented behaviour: https://docs.microsoft.com/en-us/dotnet/standard/serialization/system-text-json-polymorphism (first few lines of text).
In general this is probably a duplicate of #29937

@ramondeklein
Copy link
Author

ramondeklein commented Feb 2, 2021

@Tornhoof The documentation describes the serialization of properties definied in derived objects, where my example has issues serializing properties of the base interface. This issue doesn't have anything to do with polymorphism and therefore isn't a duplicate of #29937.

When I don't use interfaces, but use concrete classes, then it does serialize the base properties:

public class Base
{
    public int Count { get; set; }
}

public class Derived : Base
{
    public string Name { get; set; }
}

internal static class Program
{
    private static void Main(string[] args)
    {
        var obj = new Derived {Count = 1, Name = "Test"};

        // {"Count":1,"Name":"Test"}
        System.Console.WriteLine(System.Text.Json.JsonSerializer.Serialize(obj));
    }
}

In this case the serializer does serialize base properties, but only in case of interfaces it doesn't.

@Tornhoof
Copy link
Contributor

Tornhoof commented Feb 2, 2021

#29937 is more or less the original issue about polymorphic support in general.
#45189 tracks the work for .net 6.0
#41749 tracks the discovery of properties for interfaces.

@ramondeklein
Copy link
Author

Seems to be a duplicate of #41749, so I'll close this issue.

@layomia
Copy link
Contributor

layomia commented Feb 2, 2021

Closing as dup of #41749.

@ghost ghost locked as resolved and limited conversation to collaborators Mar 4, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area-System.Text.Json untriaged New issue has not been triaged by the area owner
Projects
None yet
Development

No branches or pull requests

3 participants