ohmusama
ohmusama

Reputation: 4215

Newtonsoft.JSON appends Lists when deserializing with FromObject

I've simplified my problem down to this bit of sample code using Newtonsoft.JSON.Linq and JObject.ToObject<T>()

The issue here is that in the constructor of Test a default value is added to the list Nums. However if I serialize and then deserialize the object, Newtonsoft is not replacing the list, but appending to the values set by the constructor.

I cannot change the deserialization process, as that is in a core library.

How can I set a default value for my list without duplication? Thanks.

class Test
{
    public List<int> Nums { get; set; } = new List<int>();

    public Test()
    {
        // add default value
        this.Nums.Add(0);
    }
}

class Program
{
    static void Main(string[] args)
    {
        Test job = new Test(); // job.Nums.Count == 1

        JObject jJob = JObject.FromObject(job);

        job = jJob.ToObject<Test>(); // job.Nums.Count == 2
    }
}

.Net Fiddle

Upvotes: 1

Views: 596

Answers (2)

Rob
Rob

Reputation: 27367

You need to tell it how to deserialize the object

var serializer = new JsonSerializer { 
                        ObjectCreationHandling = ObjectCreationHandling.Replace 
                };
job = jJob.ToObject<Test>(serializer);

Properly gives you 1 item after deserializing.

Upvotes: 4

Hamlet Hakobyan
Hamlet Hakobyan

Reputation: 33381

Create ctor overload which takes default value.

class Test
{
    public List<int> Nums { get; set; }

    public Test()
    {
        this.Nums = new List<int>();
    }

    public Test(int def) : this()
    {
        this.Nums.Add(def);
    }
}

Here is usage:

public class Program
{
    public static void Main(string[] args)
    {
        Test job = new Test(0); 
        Console.WriteLine(job.Nums.Count);

        JObject jJob = JObject.FromObject(job);

        job = jJob.ToObject<Test>();
        Console.WriteLine(job.Nums.Count); // This is 1 again.
    }
}

Upvotes: 2

Related Questions