我试图比较C#中的两个JSON对象并了解它们之间的差异。
将下列对象视为源对象
{
"name": "Kirk",
"age": 23,
"phone": [
123123123,
141414
],
"address": [
{
"address1": "123",
"address2": "124"
},
{
"address1": "123",
"address2": "144",
"additionalInfo": {
"pin": 123321,
"landmark": "landmark1"
}
},
{
"address1": "1223",
"addressLine2": "1242"
}
]
}而这个对象作为目标对象
{
"name": "Shawn",
"age": 23,
"phone": [
7852698,
141414
],
"address": [
{
"address1": "333",
"address2": "567"
},
{
"address1": "123",
"address2": "1414",
"additionalInfo": {
"pin": 1236381,
"landmark": "landmark3"
}
}
]
}我希望通过将目标对象中的每个属性与源对象进行比较来计算差异,并以以下格式返回响应。
[
{
"fieldName": "name",
"targetValue": "Shawn",
"sourceValue": "Kirk"
},
{
"fieldName": "address[0].address1",
"targetValue": 333,
"sourceValue": 123
},
{
"fieldName": "address[1].additionalInfo.pin",
"targetValue": 1236381,
"sourceValue": 123321
}
]fieldName只不过是指向该值的JSON路径。如何执行此操作以获得JSON对象中的差异?
发布于 2019-12-24 12:21:26
如果您想通过newtonsoft进行比较,可以使用下面的代码
public static class ExtensionJson
{
public static IEnumerable<string> CompareJson(this JObject json, JObject json2, string path)
{
var result = new List<string>();
foreach (var property in json.Properties())
{
json2.TryGetValue(property.Name, out var itemTokenTwo);
if (itemTokenTwo == null)
{
result.Add($"{{ \"fieldName\": {path}{property.Path},\"targetValue\": {property.Value},\"sourceValue\": NULL }}");
continue;
}
if (property.Value.Type == JTokenType.Array && itemTokenTwo.Type == JTokenType.Array)
{
result.AddRange(JArray.Parse(property.Value.ToString()).CompareJson(JArray.Parse(itemTokenTwo.ToString()),
(!string.IsNullOrWhiteSpace(path) ? path + "." : default) + property.Path));
continue;
}
if (property.Value.Type == JTokenType.Object && itemTokenTwo.Type == JTokenType.Object)
{
result.AddRange(JObject.Parse(property.Value.ToString()).CompareJson(JObject.Parse(itemTokenTwo.ToString()), (!string.IsNullOrWhiteSpace(path) ? path + "." : default) + property.Path));
continue;
}
if (property.Value.Type != itemTokenTwo.Type)
{
result.Add($"{{ \"fieldName\": {path}{property.Path},\"targetValue\": {property.Value},\"sourceValue\": {itemTokenTwo} }}");
continue;
}
if (property.Value.ToString() != itemTokenTwo.Value<string>().ToString())
{
result.Add($"{{ \"fieldName\": {path}.{property.Path},\"targetValue\": {property.Value},\"sourceValue\": {itemTokenTwo} }}");
}
}
return result;
}
public static IEnumerable<string> CompareJson(this JArray json, JArray json2, string path)
{
var result = new List<string>();
foreach (var jToken in json)
{
var jToken2 = json2.SelectToken(jToken.Path);
if (jToken2 == null)
{
result.Add($"{{ \"fieldName\": {path}{jToken.Path},\"targetValue\": {jToken},\"sourceValue\": NULL }}");
continue;
}
if (jToken is JObject && jToken2 is JObject)
{
result.AddRange(JObject.Parse(jToken.ToString())
.CompareJson(JObject.Parse(jToken2.ToString()), path + jToken.Path));
continue;
}
if (jToken is JArray && jToken2 is JArray)
{
result.AddRange(JArray.Parse(jToken.ToString()).CompareJson(JArray.Parse(jToken2.ToString()), path + jToken.Path));
continue;
}
if (jToken is JProperty jProperty && jToken2 is JProperty token2)
{
if (jProperty.Value != token2.Value)
{
result.Add($"{{ \"fieldName\": {path}{jProperty.Path},\"targetValue\": {jProperty.Value},\"sourceValue\": {jToken2} }}");
}
}
else if (jToken is JValue value1 && jToken2 is JValue value2)
{
if (!value1.Equals(value2))
{
result.Add(
$"{{ \"fieldName\": {path}{jToken.Path},\"targetValue\": {value1},\"sourceValue\": {value2} }}");
}
}
else if (jToken is JProperty property)
{
result.Add($"{{ \"fieldName\": {path}{property.Path},\"targetValue\": {property.Value},\"sourceValue\": {jToken2} }}");
}
else
{
result.Add($"{{ \"fieldName\": {path}{((JProperty)jToken2).Path},\"targetValue\": {((JProperty)jToken2).Value},\"sourceValue\": {jToken} }}");
}
}
return result;
}
}Main:
var json1 = @"{'name': 'Kirk',
'age': 23,
'phone': [
123123123,
141414
],
'address': [
{
'address1': '123',
'address2': '124'
},
{
'address1': '123',
'address2': '144',
'additionalInfo': {
'pin': 123321,
'landmark': 'landmark1'
}
},
{
'address1': '1223',
'addressLine2': '1242'
}
]
}";
var json2 = @"{
'name': 'Shawn',
'age': 23,
'phone': [
7852698,
141414
],
'address': [
{
'address1': '333',
'address2': '567'
},
{
'address1': '123',
'address2': '1414',
'additionalInfo': {
'pin': 1236381,
'landmark': 'landmark3'
}
}
]
}";
JObject json1O = JObject.Parse(json1);
JObject json2O = JObject.Parse(json2);
var items = JObject.Parse(json1).CompareJson(JObject.Parse(json2), json1O.Path);
foreach (var property in items)
{
Console.WriteLine(property + "\n\n");
}发布于 2019-12-24 10:48:49
请您试试下面的代码:
string jsonActual = @"{""name"":""Kirk"",""age"":23,""phone"":[123123123,141414],""address"":[{""address1"":""123"",""address2"":""124""},{""address1"":""123"",""address2"":""144"",""additionalInfo"":{""pin"":123321,""landmark"":""landmark1""}},{""address1"":""1223"",""addressLine2"":""1242""}]}";
string jsonExpected = @"{""name"":""Shawn"",""age"":23,""phone"":[7852698,141414],""address"":[{""address1"":""333"",""address2"":""567""},{""address1"":""123"",""address2"":""1414"",""additionalInfo"":{""pin"":1236381,""landmark"":""landmark3""}}]}";
var expectedObject = JsonConvert.DeserializeObject<JObject>(jsonExpected);
var actualObject = JsonConvert.DeserializeObject<JObject>(jsonActual);
List<RootObject> rootObjects = new List<RootObject>();
var obj = CompareObjects(actualObject, expectedObject, rootObjects);
string str = JsonConvert.SerializeObject(obj);请加上这两种方法
public class RootObject
{
public string fieldName { get; set; }
public object targetValue { get; set; }
public object sourceValue { get; set; }
}
private static List<RootObject> CompareObjects(JObject source, JObject target, List<RootObject> rootObjects)
{
foreach (KeyValuePair<string, JToken> sourcePair in source)
{
if (sourcePair.Value.Type == JTokenType.Object)
{
if (target.GetValue(sourcePair.Key) == null)
{
RootObject rootObject = new RootObject();
rootObject.fieldName = sourcePair.Key;
rootObject.sourceValue = sourcePair.Value;
rootObject.targetValue = "";
rootObjects.Add(rootObject);
}
else if (target.GetValue(sourcePair.Key).Type != JTokenType.Object)
{
RootObject rootObject = new RootObject();
rootObject.fieldName = sourcePair.Key;
rootObject.sourceValue = sourcePair.Value;
rootObject.targetValue = "";
rootObjects.Add(rootObject);
}
else
{
rootObjects = CompareObjects(sourcePair.Value.ToObject<JObject>(),
target.GetValue(sourcePair.Key).ToObject<JObject>(), rootObjects);
}
}
else if (sourcePair.Value.Type == JTokenType.Array)
{
if (target.GetValue(sourcePair.Key) == null)
{
RootObject rootObject = new RootObject();
rootObject.fieldName = sourcePair.Key;
rootObject.sourceValue = sourcePair.Value;
rootObject.targetValue = "";
rootObjects.Add(rootObject);
}
else
{
rootObjects=CompareArrays(sourcePair.Value.ToObject<JArray>(),
target.GetValue(sourcePair.Key).ToObject<JArray>(),rootObjects, sourcePair.Key);
}
}
else
{
JToken expected = sourcePair.Value;
var actual = target.SelectToken(sourcePair.Key);
if (actual == null)
{
RootObject rootObject = new RootObject();
rootObject.fieldName = sourcePair.Key;
rootObject.sourceValue = sourcePair.Value;
rootObject.targetValue = "";
rootObjects.Add(rootObject);
}
else
{
if (!JToken.DeepEquals(expected, actual))
{
RootObject rootObject = new RootObject();
rootObject.fieldName = sourcePair.Key;
rootObject.sourceValue = sourcePair.Value;
rootObject.targetValue = target.Property(sourcePair.Key).Value;
rootObjects.Add(rootObject);
}
}
}
}
return rootObjects;
}
private static List<RootObject> CompareArrays(JArray source, JArray target, List<RootObject> rootObjects , string arrayName = "")
{
for (var index = 0; index < source.Count; index++)
{
var expected = source[index];
if (expected.Type == JTokenType.Object)
{
var actual = (index >= target.Count) ? new JObject() : target[index];
rootObjects = CompareObjects(expected.ToObject<JObject>(),
actual.ToObject<JObject>(), rootObjects);
}
else
{
var actual = (index >= target.Count) ? "" : target[index];
if (!JToken.DeepEquals(expected, actual))
{
if (String.IsNullOrEmpty(arrayName))
{
RootObject rootObject = new RootObject();
rootObject.fieldName = "[" + index + "]";
rootObject.sourceValue = expected;
rootObject.targetValue = actual;
rootObjects.Add(rootObject);
}
else
{
RootObject rootObject = new RootObject();
rootObject.fieldName = arrayName + "[" + index + "]";
rootObject.sourceValue = expected;
rootObject.targetValue = actual;
rootObjects.Add(rootObject);
}
}
}
}
return rootObjects;
}发布于 2019-12-24 11:19:01
我通过序列化对象来比较对象。
,首先,我的模型是,
序列化json对象
public class YourClass {
public string name { get; set; }
public int age { get; set; }
public List<long> phone { get; set; }
public List<Address> address { get; set; }
}
public class Address {
public string address1 { get; set; }
public string address2 { get; set; }
public string addressLine1 { get; set; }
public string addressLine2 { get; set; }
public AdditionalInformation additionalInfo { get; set; }
}
public class AdditionalInformation {
public int pin { get; set; }
public string landmark { get; set; }
}然后从该模型反序列化
public class ResultItem {
public ResultItem(string fieldName, string targetValue, string sourceValue) {
this.fieldName = fieldName;
this.targetValue = targetValue;
this.sourceValue = sourceValue;
}
public string fieldName { get; set; }
public string targetValue { get; set; }
public string sourceValue { get; set; }
}下面的代码得到了不同之处,
string json1 = @"{'name': 'Kirk','age': 23,'phone': [123123123,141414],'address': [{'address1': '123','address2': '124'},{'address1': '123','address2': '144',
'additionalInfo': {'pin': 123321,'landmark': 'landmark1'}},{'address1': '1223','addressLine2': '1242'}]}";
string json2 = @"{'name': 'Shawn','age': 23,'phone': [7852698,141414],'address': [{'address1': '333','address2': '567'},{'address1': '123','address2': '1414',
'additionalInfo': {'pin': 1236381,'landmark': 'landmark3'}}]}";
var sample1 = JsonConvert.DeserializeObject<YourClass>(json1);
var sample2 = JsonConvert.DeserializeObject<YourClass>(json2);
var result = new List<ResultItem>();
if (!sample1.name.Equals(sample2.name))
result.Add(new ResultItem("name", sample2.name, sample1.name));
if (sample1.age != sample2.age)
result.Add(new ResultItem("age", sample2.age.ToString(), sample1.age.ToString()));
for(int i=0;i< sample1.address.Count; i++) {
if (sample1.address.Count>i && sample2.address.Count>i && sample1.address[i].address1!=sample2.address[i].address1)
result.Add(new ResultItem($"address[{i}].address1", sample2.address[i].address1, sample1.address[i].address1));
if (sample1.address.Count > i && sample2.address.Count > i && sample1.address[i].address2!=sample2.address[i].address2)
result.Add(new ResultItem($"address[{i}].address2", sample2.address[i].address2, sample1.address[i].address2));
if (sample1.address.Count > i && sample2.address.Count > i && sample1.address[i].addressLine1!=sample2.address[i].addressLine1)
result.Add(new ResultItem($"address[{i}].addressLine1", sample2.address[i].addressLine1, sample1.address[i].addressLine1));
if (sample1.address.Count > i && sample2.address.Count > i && sample1.address[i].addressLine2!=sample2.address[i].addressLine2)
result.Add(new ResultItem($"address[{i}].addressLine2", sample2.address[i].addressLine2, sample1.address[i].addressLine2));
if (sample1.address[i].additionalInfo!=null && sample2.address[i].additionalInfo!=null && sample1.address[i].additionalInfo.pin != sample2.address[i].additionalInfo.pin)
result.Add(new ResultItem($"address[{i}].additionalInfo.pin", sample2.address[i].additionalInfo.pin.ToString(), sample1.address[i].additionalInfo.pin.ToString()));
if (sample1.address.Count > i && sample2.address.Count > i && sample2.address[i].additionalInfo!=null && sample1.address[i].additionalInfo!=null && !sample1.address[i].additionalInfo.landmark.Equals(sample2.address[i].additionalInfo.landmark))
result.Add(new ResultItem($"address[{i}].additionalInfo.landmark", sample2.address[i].additionalInfo.landmark, sample1.address[i].additionalInfo.landmark));
}
string jsonResult = JsonConvert.SerializeObject(result);和jsonResult返回以下内容
[
{
"fieldName":"name",
"targetValue":"Shawn",
"sourceValue":"Kirk"
},
{
"fieldName":"address[0].address1",
"targetValue":"333",
"sourceValue":"123"
},
{
"fieldName":"address[0].address2",
"targetValue":"567",
"sourceValue":"124"
},
{
"fieldName":"address[1].address2",
"targetValue":"1414",
"sourceValue":"144"
},
{
"fieldName":"address[1].additionalInfo.pin",
"targetValue":"1236381",
"sourceValue":"123321"
},
{
"fieldName":"address[1].additionalInfo.landmark",
"targetValue":"landmark3",
"sourceValue":"landmark1"
}
]https://stackoverflow.com/questions/59466983
复制相似问题