Json.net:按对象Id合并两个Json数组



例如,我想通过对象id打乱json数组。假设我有一个json数组:

 [{"Id":"1", "a":"1", "b":"2"},
  {"Id":"2", "a":"3", "b":"1"},
  {"Id":"3", "a":"5", "b":"1"}]

我想用这个阵列来颠覆它

 [{"Id":"1", "a":"32", "b":"42"},
 {"Id":"2", "a":"3", "b":"1", "c":"23"},
  {"Id":"12", "a":"12", "b":"45"}]

预期结果应该是:

[{"Id":"1", "a":"32", "b":"42"},
  {"Id":"2", "a":"3", "b":"1", "c":"23"},
  {"Id":"3", "a":"5", "b":"1"},
  {"Id":"12", "a":"12", "b":"45"}]

您可以简单地在JArray上使用Linq,因为这些是IEnumerable<JToken>

var first = JArray.Parse(@"[{'Id':'1', 'a':'1', 'b':'2'},
            {'Id':'2', 'a':'3', 'b':'1'},
            {'Id':'3', 'a':'5', 'b':'1'}]");

var second = JArray.Parse(@"[{'Id':'1', 'a':'32', 'b':'42'},
            {'Id':'2', 'a':'3', 'b':'1', 'c':'23'},
            {'Id':'12', 'a':'12', 'b':'45'}]");
var resultAsEnumerable = first.Concat(second)
                              .GroupBy(t => t["Id"])
                              .Select(g => g.Last());

如果你需要你的结果作为JArray,你可以很容易地将结果转换为:

var resultAsJArray = new JArray(resultAsEnumerable.ToArray());

我认为这在C#中可以很容易地完成。如果你把你的实体映射到这样的东西:

[DataContract]
public class Entity
{
    [DataMember(Name = "Id")]
    public string Id { get; set; }
    [DataMember(Name = "a")]
    public int? A { get; set; }
    [DataMember(Name = "b")]
    public int? B { get; set; }
    [DataMember(Name = "c")]
    public int? C { get; set; }
}

我认为使用LINQ不可能执行所需的操作,但好的旧foreach将解决您的问题。

编辑:事实上,在看过@vadim gremyachev的回答后,我认为它可以很好地使用LINQ:

var l1 = JsonConvert.DeserializeObject<IList<Entity>>(
    @"[{""Id"":""1"", ""a"":""1"", ""b"":""2""}, 
       {""Id"":""2"", ""a"":""3"", ""b"":""1""}, 
       {""Id"":""3"", ""a"":""5"", ""b"":""1""}]");
var l2 = JsonConvert.DeserializeObject<IList<Entity>>(
    @"[{""Id"":""1"", ""a"":""32"", ""b"":""42""},
       {""Id"":""2"", ""a"":""3"", ""b"":""1"", ""c"":""23""},
       {""Id"":""12"", ""a"":""12"", ""b"":""45""}]");
// LINQ
var res = l1.Concat(l2).GroupBy(x => x.Id).Select(x => x.Last()).ToList();
// Foraech
var res2 = new List<Entity>(l1);
foreach (var l2Entity in l2)
{
    var resEntity = res2.FirstOrDefault(x => x.Id == l2Entity.Id);
    if (resEntity == null)
    {
        res2.Add(l2Entity);
    }
    else
    {
        res2[res2.IndexOf(resEntity)] = l2Entity;
    }
}

然后,您可以将res列表序列化回JSON,就完成了:

var json = JsonConvert.SerializeObject(res);

生成的JSON将是:

[
    {"Id":"1","a":32,"b":42},
    {"Id":"2","a":3,"b":1,"c":23},
    {"Id":"3","a":5,"b":1},
    {"Id":"12","a":12,"b":45}
]

您也可以使用l1而不创建res,当然这取决于您的情况。您可能还希望在合并完成后按键对生成的集合进行排序。

var x = JArray.Parse(@"[{'Id':'1', 'a':'1', 'b':'2'},
                        {'Id':'2', 'a':'3', 'b':'1'},
                        {'Id':'3', 'a':'5', 'b':'1'}]");

var y = JArray.Parse(@"[{'Id':'1', 'a':'32', 'b':'42'},
                        {'Id':'2', 'a':'3', 'b':'1', 'c':'23'},
                        {'Id':'12', 'a':'12', 'b':'45'}]");
//1. Union arrays skipping items that already exist
x.Merge(y, new JsonMergeSettings
        {
            MergeArrayHandling = MergeArrayHandling.Union,
        });
//2. Get distinct items by key (Id) 
var result = x.GroupBy(i => i["Id"]).Select(g => g.Last()).ToList();

我尝试了其中的几个答案,它们只对我起到了部分作用,排序结果json留给读者练习,你可能希望输入json没有ID作为字符串,这样才能正常工作。使用.net core 3.1进行测试。

var input1 = JsonConvert.DeserializeObject<JArray>(@"[  {'Id':'1', 'a':'1', 'b':'2'},
                                                        { 'Id':'2', 'a':'3', 'b':'1'},
                                                        { 'Id':'3', 'a':'5', 'b':'1'}]");
var input2 = JsonConvert.DeserializeObject<JArray>(@" [  {'Id':'1', 'a':'32', 'b':'42'},
                                                         {'Id':'2', 'a':'3', 'b':'1', 'c':'23'},
                                                         {'Id':'12', 'a':'12', 'b':'45'}]");
//you may want this the other way depending on what your trying to do
//input1.Merge(input2);
input2.Merge(input1);
var res = new List<dynamic>();
foreach (var x in input2.GroupBy(x => x["Id"]).ToList())
{
      var newItem = new ExpandoObject();
      foreach (var y in x)
      {
            foreach (JProperty z in y)
            {
                 newItem.TryAdd(z.Name, z.Value);
            }
       }
       res.Add(newItem);
 }
 Console.WriteLine(JsonConvert.SerializeObject(res));
 Console.ReadLine();

输出:

[{
        "Id": "1",
        "a": "32",
        "b": "42"
    }, {
        "Id": "2",
        "a": "3",
        "b": "1",
        "c": "23"
    }, {
        "Id": "12",
        "a": "12",
        "b": "45"
    }, {
        "Id": "3",
        "a": "5",
        "b": "1"
    }
]

相关内容

  • 没有找到相关文章

最新更新