Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JsonSerializer behaves not as expected when the specifc class is casted to something else

Im trying to migrate from json.net to microsoft's json and found something that behaves very differently.

Let's use this simplified example:

public interface IName
{
    string Name { get; set; }

}

public class Person : IName
{
    public string Name { get; set; }
    public int Age { get; set; }
}

public void Foo() 
{
   IName p = new Person {Age = 4, Name = "Waldo"};
   var s1 = System.Text.Json.JsonSerializer.Serialize(p); // --> {"Name":"Waldo"}
   var s2 = Newtonsoft.Json.JsonConvert.SerializeObject(p); // --> {"Name":"Waldo","Age":4}
}

Microsoft's Serializers serializes properties from IName JSON.NET serializes properties from Person

Is there a way to configure it so that it would work like JSON.NET? The options that I could pass do not indicate that this is configurable. Did I overlook something?

like image 486
gsharp Avatar asked Jan 01 '23 14:01

gsharp


1 Answers

This is because the serializer uses the type of the generic parameter, not the type of the passed value:

public static string Serialize<TValue>(TValue value, JsonSerializerOptions options = null)
{
    return WriteCoreString(value, typeof(TValue), options);
}

This passes typeof(IName) to WriteCoreString, and on that type ultimately reflection is performed.

You can work around this by explicitly passing the type to the overload that accepts that:

var s3 = System.Text.Json.JsonSerializer.Serialize(p, p.GetType());

This returns:

{"Name":"Waldo","Age":4}

Casting to object also works, as the code then calls value.GetType():

var s4 = System.Text.Json.JsonSerializer.Serialize((object)p);
like image 94
CodeCaster Avatar answered Jan 27 '23 19:01

CodeCaster