例如,如果我有以下json文本:
object1{
field1: value1;
field2: value2;
field3: value3;
}
object1{
field1: value1;
field2: newvalue2;
field3: value3;
}
我需要在c#中读取文件并显示差异。即它可以返回以下对象:
differences {
object1: { field: field2, old_value: value2, new_value: newvalue2}
}
是否有一些API或建议来执行此操作?
答案 0 :(得分:4)
我建议您使用Weakly-Typed JSON Serialization并编写一个使用JsonObject的例程:
String JsonDifferenceReport(String objectName,
JsonObject first,
JsonObject second)
{
if(String.IsNullOrEmpty(objectName))
throw new ArgumentNullException("objectName");
if(null==first)
throw new ArgumentNullException("first");
if(null==second)
throw new ArgumentNullException("second");
List<String> allKeys = new List<String>();
foreach(String key in first.Keys)
if (!allKeys.Any(X => X.Equals(key))) allKeys.Add(key);
foreach(String key in second.Keys)
if (!allKeys.Any(X => X.Equals(key))) allKeys.Add(key);
String results = String.Empty;
foreach(String key in allKeys)
{
JsonValue v1 = first[key];
JsonValue v1 = second[key];
if (((null==v1) != (null==v2)) || !v1.Equals(v2))
{
if(String.IsNullOrEmpty(results))
{
results = "differences: {\n";
}
results += "\t" + objectName + ": {\n";
results += "\t\tfield: " + key + ",\n";
results += "\t\toldvalue: " + (null==v1)? "null" : v1.ToString() + ",\n";
results += "\t\tnewvalue: " + (null==v2)? "null" : v2.ToString() + "\n";
results += "\t}\n";
}
}
if(!String.IsNullOrEmpty(results))
{
results += "}\n";
}
return results;
}
您是否可以在JsonValue
v1和v2中递归获取报告,而不是像我在这里一样使用他们的字符串表示。
如果您想要递归,可能会改变上面的内容:
if ((null==v1) || (v1.JsonType == JsonType.JsonPrimitive)
|| (null==v2) || (v2.JsonType == JsonType.JsonPrimitive))
{
results += "\t\tfield: " + key + ",\n";
results += "\t\toldvalue: " + (null==v1) ? "null" : v1.ToString() + ",\n";
results += "\t\tnewvalue: " + (null==v2) ? "null" : v2.ToString() + "\n";
}
else
{
results + JsonDifferenceReport(key, v1, v2);
}
-Jesse
答案 1 :(得分:1)
出于某种原因,我无法在我的Web API项目中使用JsonObject。我使用JSON.Net,下面是我获取差异的方法。它将给出一系列差异。
private static string GetJsonDiff(string action, string existing, string modified, string objectType)
{
// convert JSON to object
JObject xptJson = JObject.Parse(modified);
JObject actualJson = JObject.Parse(existing);
// read properties
var xptProps = xptJson.Properties().ToList();
var actProps = actualJson.Properties().ToList();
// find differing properties
var auditLog = (from existingProp in actProps
from modifiedProp in xptProps
where modifiedProp.Path.Equals(existingProp.Path)
where !modifiedProp.Value.Equals(existingProp.Value)
select new AuditLog
{
Field = existingProp.Path,
OldValue = existingProp.Value.ToString(),
NewValue = modifiedProp.Value.ToString(),
Action = action, ActionBy = GetUserName(),
ActionDate = DateTime.UtcNow.ToLongDateString(),
ObjectType = objectType
}).ToList();
return JsonConvert.SerializeObject(auditLog);
}
答案 2 :(得分:0)
我已经构建了自己的Json比较方法。它使用Newtonsoft.Json.Linq。
public static JObject FindDiff(this JToken Current, JToken Model)
{
var diff = new JObject();
if (JToken.DeepEquals(Current, Model)) return diff;
switch(Current.Type)
{
case JTokenType.Object:
{
var current = Current as JObject;
var model = Model as JObject;
var addedKeys = current.Properties().Select(c => c.Name).Except(model.Properties().Select(c => c.Name));
var removedKeys = model.Properties().Select(c => c.Name).Except(current.Properties().Select(c => c.Name));
var unchangedKeys = current.Properties().Where(c => JToken.DeepEquals(c.Value, Model[c.Name])).Select(c => c.Name);
foreach (var k in addedKeys)
{
diff[k] = new JObject
{
["+"] = Current[k]
};
}
foreach (var k in removedKeys)
{
diff[k] = new JObject
{
["-"] = Model[k]
};
}
var potentiallyModifiedKeys = current.Properties().Select(c => c.Name).Except(addedKeys).Except(unchangedKeys);
foreach (var k in potentiallyModifiedKeys)
{
diff[k] = FindDiff(current[k], model[k]);
}
}
break;
case JTokenType.Array:
{
var current = Current as JArray;
var model = Model as JArray;
diff["+"] = new JArray(current.Except(model));
diff["-"] = new JArray(model.Except(current));
}
break;
default:
diff["+"] = Current;
diff["-"] = Model;
break;
}
return diff;
}