JSON.NET - 使用List进行对象更新

时间:2015-07-14 09:38:30

标签: c# json json.net

有人可以建议更新Cheese.Producers列表中的项目的方法吗?

我有以下课程:

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>();
    }
}

在主代码中,我有一个对象(gouda),我想根据从文件中读取的JSON来更新。

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);
}

JSON更新文件:

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

主要问题是,当调用PopulateObject时,不会更新Producers列表项,而是添加2个新成员。其他领域似乎工作得很好。 有什么建议吗?

2 个答案:

答案 0 :(得分:1)

试试这个:

                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();

您需要稍微更改JSON格式:

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

    },
    {
      'Name': 'prod3',
      'Rating': 300
    }
  ]
}

我们走了:

enter image description here

希望这有帮助。

答案 1 :(得分:1)

我觉得没有办法按照你正在使用的格式限制完成你想要做的事情。

您希望保留独特的制作人,但他们正在使用一系列制作人,而这些制作人无法保留唯一性。

所以,AFAICT,你有两条路。

1 - 更改json对象中的producer数组,该对象将反序列化为字典。

2 - 您将JSON.NET的使用限制在反序列化中,然后在您的Cheese类中实现一个方法“merge”,并进行相关的唯一性检查。

如果您需要对此方向进行改进,请与我们联系。

修改

首先,将您的Cheese类改为:

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>();
    }
}

你的Json相应地:

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

其他一切都应该是平等的。 字典的好处是它可以处理键的唯一性。

我在数据中留下了一些冗余,以简化代码。 你可以删除

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

来自Json的行,在反序列化后填充相应的name属性,如:

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

希望它有所帮助。