Reputation: 45
List object1
[ { "empId":10001, "empName":"test1" }, { "empId":10002, "empName":"test2" } ]
List object2
[ { "empId":10001, "emailAddress":"[email protected]" }, { "empId":10002, "emailAddress":"[email protected]" } ]
Trying to get the merge result which matches "empId" in both objects.
Result
[
{
"empId":10001,
"empName":"test1",
"emailAddress":"[email protected]"
},
{
"empId":10002,
"empName":"test2",
"emailAddress":"[email protected]"
}
]
I have tried https://www.newtonsoft.com/json/help/html/MergeJson.htm. but not able to do the matching logic "empId"
Upvotes: 2
Views: 947
Reputation: 8472
The Merge()
function you are using is not the only thing you need. You need LINQ's Join()
to "merge" the two lists and then Merge()
to merge individual items:
var xs = JArray
.Parse(@"[
{""empId"": 10001, ""empName"": ""test1""},
{""empId"": 10002, ""empName"": ""test2""}
]")
.Values<JObject>();
var ys = JArray
.Parse(@"[
{""empId"": 10001, ""emailAddress"": ""[email protected]""},
{""empId"": 10002, ""emailAddress"": ""[email protected]""}
]")
.Values<JObject>();
var merged = xs.Join(
ys,
x => x["empId"],
y => y["empId"],
(x, y) => { x.Merge(y); return x; });
Note that you can probably just cast the dynamic
types back to JObject
for much easier handling.
Upvotes: 1
Reputation: 35716
Here is some code that will Join and Merge, working here.
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Dynamic;
using System.Linq;
using Newtonsoft.Json;
public class Program
{
public static void Main()
{
var list1 = new[]
{
new { empId = 10001, empName = "test1" },
new { empId = 10002, empName = "test2" }
};
var list2 = new[]
{
new { empId = 10001, emailAddress = "[email protected]" },
new { empId = 10002, emailAddress = "[email protected]" }
};
var results1 = list1.MergeJoin(list2, e => e.empId);
Console.WriteLine($"{nameof(results1)}:");
Console.WriteLine(JsonConvert.SerializeObject(results1, Formatting.Indented));
Console.WriteLine();
IList<dynamic> dynamicList1 = new List<dynamic>
{
new { empId = 10001, empName = "test1", utterance = "wibble" },
new { empId = 10002, empName = "test2", expression = "bemused" }
};
IList<dynamic> dynamicList2 = new List<dynamic>
{
new { empId = 10001, emailAddress = "[email protected]", IQ = "moron" },
new { empId = 10002, emailAddress = "[email protected]", smell = "cheesy" }
};
var results2 = dynamicList1.MergeJoin(dynamicList2, e => e.empId);
Console.WriteLine($"{nameof(results2)}:");
Console.WriteLine(JsonConvert.SerializeObject(results2, Formatting.Indented));
}
}
public static class Extensions
{
public static IEnumerable<dynamic> MergeJoin<TKey>(
this IEnumerable<dynamic> outer,
IEnumerable<dynamic> inner,
Func<dynamic, TKey> keyAccessor)
{
return outer.Join(
inner,
keyAccessor,
keyAccessor,
Merge);
}
public static dynamic Merge(dynamic left, dynamic right)
{
IDictionary<string, object> dictionary1 = GetKeyValueMap(left);
IDictionary<string, object> dictionary2 = GetKeyValueMap(right);
var result = new ExpandoObject();
var d = result as IDictionary<string, object>;
foreach (var pair in dictionary1.Concat(dictionary2))
{
d[pair.Key] = pair.Value;
}
return result;
}
private static IDictionary<string, object> GetKeyValueMap(object values)
{
if (values == null)
{
return new Dictionary<string, object>();
}
var map = values as IDictionary<string, object>;
if (map != null)
{
return map;
}
map = new Dictionary<string, object>();
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
{
map.Add(descriptor.Name, descriptor.GetValue(values));
}
return map;
}
}
This should output,
results1:
[
{
"empId": 10001,
"empName": "test1",
"emailAddress": "[email protected]"
},
{
"empId": 10002,
"empName": "test2",
"emailAddress": "[email protected]"
}
]
results2:
[
{
"empId": 10001,
"empName": "test1",
"utterance": "wibble",
"emailAddress": "[email protected]",
"IQ": "moron"
},
{
"empId": 10002,
"empName": "test2",
"expression": "bemused",
"emailAddress": "[email protected]",
"smell": "cheesy"
}
]
Upvotes: 2