我想通过对象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"}]
答案 0 :(得分:2)
我认为可以在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
,这取决于您的情况。您可能还希望在合并完成后按键对结果集合进行排序。
答案 1 :(得分:1)
您可以在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());
答案 2 :(得分:0)
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();
答案 3 :(得分:0)
我尝试了其中的一些答案,但它们只对我有用,将结果 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"
}
]