Bogdan N
Bogdan N

Reputation: 43

JSON.NET - Object update with List

Could someone suggest a method of updating the items in the Cheese.Producers list?

I have the following classes:

class Producer
{
    public string Name { get; set; }
    public int Rating { get; set; }

    public Producer()
    {
    }

    public Producer(string name, int rating)
    {
        Name = name;
        Rating = rating;
    }
}

class Cheese
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Taste { get; set; }
    public List<Producer> Producers { get; set; }

    public Cheese()
    {
        Producers = new List<Producer>();
    }

    public Cheese(string name, int age)
    {
        Name = name;
        Age = age;
        Producers = new List<Producer>();
    }

    public Cheese(string name, int age, string taste)
    {
        Name = name;
        Age = age;
        Taste = taste;
        Producers = new List<Producer>();
    }
}

In the main code I have an object(gouda) that I want to update based on a JSON read from a file.

static void Main(string[] args)
{
    Producer prod1 = new Producer("prod1", 5);
    Producer prod2 = new Producer("prod2", 6);
    Producer prod3 = new Producer("prod3", 7);

    Cheese gouda = new Cheese("Gouda", 5, "Mild");
    gouda.Producers.Add(prod1);
    gouda.Producers.Add(prod2);
    gouda.Producers.Add(prod3);

    string propertiesToBeAdded = File.ReadAllText("properties.txt");
    JsonSerializerSettings jsonSerializerSettings = new JsonSerializerSettings
    {
        ObjectCreationHandling = ObjectCreationHandling.Reuse
    };
    JsonConvert.PopulateObject(propertiesToBeAdded, gouda, jsonSerializerSettings);
}

The JSON update file:

{
  "Name": "Hard Blue",
  "Taste": "Sharp",
  "Producers": [
    {
      "Name": "prod1",
      "Rating": 100
    },
    {
      "Name": "prod3",
      "Rating": 300
    }
  ]
}

The major problem is that when the PopulateObject is called, instead of updating the Producers list items, 2 new members are added. The other fields seem to work just fine. Any suggestions?

Upvotes: 4

Views: 1761

Answers (2)

Alberto Chiesa
Alberto Chiesa

Reputation: 7350

I feel there is no way to accomplish simply what you want to do, with the constraints of the format you're using.

You want to retain unique producers, but are using an array of producers, wich has no way of preserving uniqueness.

So, AFAICT, you have two roads.

1 - you change the producers array in an json object, which would deserialize as a dictionary.

2 - you restrict the use of JSON.NET to the deserialization, and then implement a method "merge" in your Cheese class, with the relevant uniqueness checks.

If you need a refinement over this directions, let me know.

EDIT

First, change your Cheese class into this:

class Cheese
{
    public string Name { get; set; }
    public int Age { get; set; }
    public string Taste { get; set; }
    public Dictionary<String, Producer> Producers { get; set; }

    public Cheese()
    {
        Producers = new Dictionary<String, Producer>();
    }

    public Cheese(string name, int age)
    {
        Name = name;
        Age = age;
        Producers = new List<Producer>();
    }

    public Cheese(string name, int age, string taste)
    {
        Name = name;
        Age = age;
        Taste = taste;
        Producers = new List<Producer>();
    }
}

And your Json accordingly:

{
  "Name": "Hard Blue",
  "Taste": "Sharp",
  "Producers": {
    "prod1": {
      "Name": "prod1",
      "Rating": 100
    },
    "prod3": {
      "Name": "prod3",
      "Rating": 300
    }
  }
}

Everything else should be equal. The nice thing about the dictionary is that it takes care of the uniqueness of the keys.

I left some redundancy in the data, to simplify the code. You could remove the

"Name": "prod1",
...
"Name": "prod3",

lines from the Json, populating the corresponding name property after deserialization, something like:

foreach(var prod in gouda.Producers.Keys)
{
  gouda.Producers[prod].Name = prod;
}

Hope it helps.

Upvotes: 1

Amit Kumar Ghosh
Amit Kumar Ghosh

Reputation: 3726

Try this:

                Producer prod1 = new Producer("prod1", 5);
                Producer prod2 = new Producer("prod2", 6);
                Producer prod3 = new Producer("prod3", 7);

                Cheese gouda = new Cheese("Gouda", 5, "Mild");
                gouda.Producers.Add(prod1);
                gouda.Producers.Add(prod2);
                gouda.Producers.Add(prod3);

                var propertiesToBeAdded = File.ReadAllText(@"C:\json path");
                
                var settings = new JsonMergeSettings
                {
                    MergeArrayHandling = MergeArrayHandling.Merge
                };

                var o1 = JObject.Parse(JsonConvert.SerializeObject(gouda));

                o1.Merge(JObject.Parse(propertiesToBeAdded), settings);

                var o = o1.ToString();

And you need to change your JSON format a bit :

{
  'Name': 'Hard Blue',
  'Taste': 'Sharp',
  'Producers': [
    {
      'Name': 'prod1',
      'Rating': 100
    },
    {
      
    },
    {
      'Name': 'prod3',
      'Rating': 300
    }
  ]
}

Here we go:

enter image description here

Hope this helps.

Upvotes: 1

Related Questions