christo8989
christo8989

Reputation: 6826

Newtonsoft Deserialization and Properties Getter Method

Newtonsoft's json Deserializer, JsonConvert.DeserializeObject<T>(json); was deserializing my object wrong because it would not instantiate one of the properties. I wrote up a dotnetfiddle which shows the same problem.

Classes:

public class Right
{
    private Property _property;
    public Property Property 
    { 
        get { return _property; } 
        set { _property = value ?? new Property(); } 
    }
}

public class Wrong
{
    private Property _property;
    public Property Property  
    { 
        get { return _property ?? new Property(); } 
        set { _property = value; } 
    }
}

public class Property
{
    public string Text { get; set; }
}

Main Program:

using System;
using Newtonsoft.Json;

public class Program
{
    public static void Main()
    {
        //Instantiate
        var right = new Right();
        var wrong = new Wrong();

        //Initialize property
        right.Property = new Property() { Text = "Right!" };
        wrong.Property = new Property() { Text = "Wrong?" };

        //Serialize
        var jsonRight = JsonConvert.SerializeObject(right);
        var jsonWrong = JsonConvert.SerializeObject(wrong);

        //Print json
        Console.WriteLine(jsonRight);       
        Console.WriteLine(jsonWrong);

        //Deserialize
        var dRight = JsonConvert.DeserializeObject<Right>(jsonRight);
        var dWrong = JsonConvert.DeserializeObject<Wrong>(jsonWrong);

        //Print property
        Console.WriteLine("'" + dRight.Property.Text + "'");
        Console.WriteLine("'" + dWrong.Property.Text + "'");
    }
}

Output:

// {"Property":{"Text":"Right!"}}
// {"Property":{"Text":"Wrong?"}}
// 'Right!'
// ''

Why can't the Deserializer do its thang when I'm doing return _property ?? new Property(); inside the getter method?

Upvotes: 3

Views: 1439

Answers (1)

brainless coder
brainless coder

Reputation: 6430

Because -

public class Wrong
{
    private Property _property;
    public Property Property  
    { 
        get { return _property ?? new Property(); } // no assignment done to _property.
        set { _property = value; } 
    }
}

This creates a new property whenever the property is null. But it does not update the _property member, it is still the old one and still the null one. So, every time you use the property it creates a new object and returns it and forgets the reference when it runs out of scope. If does not matter whether you are using Json Converter or anything. This is a very very very destructive appoach.

The right approach is this one -

public class Right
{
    private Property _property;
    public Property Property 
    { 
        get { return _property; } 
        set { _property = value ?? new Property(); }  //initialized and assigned to _property
    }
}

It initializes the property with new object if it is null and assigns to the member _property. In future whenever you use this property, it has the proper reference and works properly.

BTW: This is not a problem. This is the required behavior.

Upvotes: 4

Related Questions