18/08/2017

Json.net also tricked me

Home



Recently, I was tricked by Roslyn, today by Json.NET. My bloody luck ;) Let's look at the following two very simple classes. Class A has one readonly property and I had to define a special constructor to allow Json.NET to set this property. B is also simple. It has one property, this time of type A with some default value.

public class A
{
   public string Name { get; }

   [JsonConstructor]
   public A(string name) { Name = name; }
}

public class B
{
   public A Test { get; set; } = new A("Default");

}
Now let's serialize an instance of B in the following way:
var serializedText = JsonConvert.SerializeObject(new B() { Test = new A("Fun") { } });
In the result, as expected, we will get the following text:

{"Test":{"Name":"Fun"}}

Now let's deserialize this string:
var result = (B)JsonConvert.DeserializeObject(serializedText, typeof(B));
Now question for 1 million dollars. What will be the value of A.Test.Name in a deserialized object. If you say Fun you are wrong! It will be Default!

I was surprised and I spent some time investigating this issue. Why did it happen? Well, it seems to me that when Json.NET creates a new object during deserialization and it notices that some property of this object is not null, them this default value will not be overriden. If it's a problem, there are at least 2 solutions:
  • Remove a default value for this property. It doesn't matter if it is set in a constructor of via a property initializer.
  • Add a special constructor. For instance, for class B it'll look as below. This constructor instructs Json.NET that Test property must be set even if a default value exists.
public class B
{
   public A Test { get; set; } = new A("Default");

   public B() {}

   [JsonConstructor]
   public B(A test) { Test = test; }
}


*The picture at the beginning of the post comes from own resources and shows elephants from Warsaw zoo.

22 comments:

Peter Lanoie said...

Isn't the problem much simpler than property construction? A.Name is written as read only. Whether the deserializer creates an instance of A to assign to B.Test or uses an existing instance (your "Default") is irrelevant. B.Test.Name is still read-only.

Peter Lanoie said...

So I re-read your post several times (I think all the As and Bs were confusing me). I think I jumped the gun on my first comment before I fully understood the solution. More importantly, I don't think I've used the JsonConstructor attribute so I didn't realize what it was accomplishing. I've typically solve the problem you describe by just making the properties read/write.

Michał Komorowski said...

@Peter Lanoie Thanks for the comment. Next time I will use more descriptive names for classes ;)

As to "making the properties read/write". It should help to make A.Name writable. However, it is not always possible.

jogibear9988 said...

I've ran into an issue with default values and Preserve References, see https://github.com/JamesNK/Newtonsoft.Json/issues/1351

Tyler Brinkley said...

Upon deserialization you should use var result = JsonConvert.DeserializeObject<B>(serializedText, new JsonSerializerSettings { ObjectCreationHandling = ObjectCreationHandling.Replace });

Michał Komorowski said...

@Tyler Brinkley - Thanks, I didn't know this one.

pension said...
This comment has been removed by a blog administrator.
OpioidClinicsinjohnsonCityTN said...
This comment has been removed by a blog administrator.
shahbaz said...
This comment has been removed by a blog administrator.
shahbaz said...
This comment has been removed by a blog administrator.
OpioidClinicsinjohnsonCityTN said...
This comment has been removed by a blog administrator.
shahbaz said...
This comment has been removed by a blog administrator.
OpioidClinicsinjohnsonCityTN said...

Hello Thanks for sharing nice information with us. i like your post and all you share with us is uptodate and quite informative, i would like to bookmark the page so i can come here again to read you, as you have done a wonderful jobraleigh roofing contractor

OpioidClinicsinjohnsonCityTN said...

Can I simply say what a aid to search out somebody who actually is aware of what theyre talking about on the internet. You positively know tips on how to carry an issue to light and make it important. Extra individuals need to read this and perceive this aspect of the story. I cant consider youre no more popular since you undoubtedly have the gift.Raingo Raleigh

Sally Watkins said...

This is great content! I am swept away by your presentation and unique viewpoints. I agree with so much of your article. I’ll come back.richmond hill homes for sale

OpioidClinicsinjohnsonCityTN said...

It is so sad that a foreign company owned some property in the us. There has no declaration about this land and if the land registry records was not there, people may not have know about this fact.Home for sale in Bucks County

OpioidClinicsinjohnsonCityTN said...

Hmm!! This blog is really cool, I’m so lucky that I have reached here and got this awesome information.property in bangalore

OpioidClinicsinjohnsonCityTN said...


Very nice tips which anyone can apply when selling their property. A word of mouth through friends and family is also fantastic since you can get a buyer just there!Forett Bukit Timah

Omego2K said...

that did the trick for me. Anyway for it to not check the value before hand? Like in the case of a string property.

OpioidClinicsinjohnsonCityTN said...

We are genuinely appreciative for your blog section. You will find a lot of strategies in the wake of setting off to your post. I was exactly checking for. An obligation of appreciation is all together for such post and please keep it up.chattanooga homes for sale

OpioidClinicsinjohnsonCityTN said...
This comment has been removed by a blog administrator.
Smith said...

You might not be aware that until 2011, the railway station at Schofields was a basic single platform located across the road from where the Chinese takeaway, until it was relocated to it’s current location closer to the (then only planned!) new developments, much to the vocal distaste of the locals residing in the “old” Schofields village.Penrose floor plan

Post a Comment