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

Polymorphic deserialization requires disriminator property order to be first in json. #78338

Closed
vladimir-ilnytskyi opened this issue Nov 14, 2022 · 4 comments

Comments

@vladimir-ilnytskyi
Copy link

vladimir-ilnytskyi commented Nov 14, 2022

Description

If discriminator property is not placed as a FIRST property then polymorphic object converter doesn't find it.
As json property order might be any, it puts a big inconvenience for example for frontend to actually send discriminator as first property
{ "nonDiscrimProperty": 1, "discrimProperty": 1 } // discrimProperty is discriminator

Second inconvenience is that i have to use JsonIgnore attribute on the object if i want this property to be present in C# class.

Reproduction Steps

`
[JsonDerivedType(typeof(Cat), 1)]
[JsonPolymorphic(TypeDiscriminatorPropertyName = nameof(Type))]
public abstract class Animal
{
public string Name { get; set; }
[JsonIgnore] // workaround, serialize duplicates discriminator in json and makes json invalid
public virtual int Type { get; set; }
}

public class Cat : Animal
{
public override int Type => 1;
}

var animal = new Cat { Name = "cat" };
var array = new Animal[] { animal };
var json = JsonSerializer.Serialize(array); // polymorphically serialize array of animals
var obj = JsonSerializer.Deserialize<Animal[]>(json); // ok

var obj2 = JsonSerializer.Deserialize<Animal[]>("[{"Type": 1}]"); // ok
var obj3 = JsonSerializer.Deserialize<Animal[]>("[{"Name":"mycat","Type": 1}]"); // fails because converter count find discriminator as first property`

Expected behavior

`var obj3 = JsonSerializer.Deserialize<Animal[]>("[{"Name":"mycat","Type": 1}]"); // should deserialize the object``

Actual behavior

`var obj3 = JsonSerializer.Deserialize<Animal[]>("[{"Name":"mycat","Type": 1}]"); // fails because converter count find discriminator as first property``

Regression?

No response

Known Workarounds

force all parties to send discriminator as first object.
use jsonignore attribute if you dont want your property to be duplicated with the discriminator during serialization.
or [JsonDerivedType(typeof(Animal))] to exclude discriminator from serialization

Configuration

system.text.json 7.0.0

Other information

No response

@ghost ghost added the untriaged New issue has not been triaged by the area owner label Nov 14, 2022
@ghost
Copy link

ghost commented Nov 14, 2022

Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis
See info in area-owners.md if you want to be subscribed.

Issue Details

Description

If discriminator property is not placed as a FIRST property then polymorphic object converter doesn't find it.
As json property order might be any, it puts a big inconvenience for example for frontend to actually send discriminator as first property
{ "nonDiscrimProperty": 1, "discrimProperty": 1 } // discrimProperty is discriminator

Second inconvenience is that i have to use JsonIgnore attribute on the object if i want this property to be present in C# class.

Reproduction Steps

`
[JsonDerivedType(typeof(Cat), 1)]
[JsonPolymorphic(TypeDiscriminatorPropertyName = nameof(Type))]
public abstract class Animal
{
public string Name { get; set; }
[JsonIgnore] // workaround, serialize duplicates discriminator in json and makes json invalid
public virtual int Type { get; set; }
}

public class Cat : Animal
{
public override int Type => 1;
}

var animal = new Cat { Name = "cat" };
var array = new Animal[] { animal };
var json = JsonSerializer.Serialize(array); // polymorphically serialize array of animals
var obj = JsonSerializer.Deserialize<Animal[]>(json); // ok

var obj2 = JsonSerializer.Deserialize<Animal[]>("[{"Type": 1}]"); // ok
var obj3 = JsonSerializer.Deserialize<Animal[]>("[{"Name":"mycat","Type": 1}]"); // fails because converter count find discriminator as first property`

Expected behavior

`var obj3 = JsonSerializer.Deserialize<Animal[]>("[{"Name":"mycat","Type": 1}]"); // should deserialize the object``

Actual behavior

`var obj3 = JsonSerializer.Deserialize<Animal[]>("[{"Name":"mycat","Type": 1}]"); // fails because converter count find discriminator as first property``

Regression?

No response

Known Workarounds

force all parties to send discriminator as first object.
use jsonignore attribute if you dont want your property to be duplicated with the discriminator during serialization.

Configuration

system.text.json 7.0.0

Other information

No response

Author: vladimir-ilnytskyi
Assignees: -
Labels:

area-System.Text.Json

Milestone: -

@Tornhoof
Copy link
Contributor

See #72604

@vladimir-ilnytskyi
Copy link
Author

@Tornhoof thanks! seems like a dup, but according to json spec it is NORMAL to have random order of props...
I don't get how do why do i have to force browser to send ordered properties =(

@layomia
Copy link
Contributor

layomia commented Nov 22, 2022

Duplicate of #72604.

@layomia layomia closed this as completed Nov 22, 2022
@ghost ghost removed the untriaged New issue has not been triaged by the area owner label Nov 22, 2022
@ghost ghost locked as resolved and limited conversation to collaborators Dec 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Projects
None yet
Development

No branches or pull requests

3 participants