是否有一个库(C#首选)来解决我称之为多级级联JSON的问题?
这是我的意思的一个例子:(Pseudocode / C#)
var json1 = @"{
""firstName"": ""John"",
""lastName"": ""Smith""
}";
var json2 = @"{
""firstName"": ""Albert""
}";
var json3 = @"{
""phone"": ""12345""
}";
var cascadingJSON = JSON.Cascade(json1, json2, json3);
结果(与CSS相同的行为)
{
"firstName"": "Albert", /*Overridden*/
"lastName"": "Smith", /*Inherited*/
"phone"": "12345" }"; /*Added*/
}
编辑1 - 更复杂的示例
const string json1 =
@"{
""firstName"": ""John"",
""lastName"": ""Smith"",
""age"": 25,
""address"":
{
""streetAddress"": ""21 2nd Street"",
""city"": ""New York"",
""state"": ""NY"",
""postalCode"": ""10021""
},
""phoneNumber"":
[
{
""type"": ""home"",
""number"": ""212 555-1234""
},
{
""type"": ""fax"",
""number"": ""646 555-4567""
}
]
}";
const string json2 =
@"{
""firstName"": ""John2"",
""lastName"": ""robert"",
""age"": 25,
""address"":
{
""state"": ""FL"",
},
""phoneNumber"":
[
{
""type"": ""fax"",
""number"": ""222 222-2222""
},
{
""type"": ""iphone"",
""number"": ""111 111-1111""
}
]
}";
const string json3 =
@"{
""firstName"": ""John3"",
""father"": ""guy""
}";
const string expectedResult =
@"{
""firstName"": ""John3"",
""lastName"": ""robert"",
""age"": 25,
""father"": ""guy"",
""address"":
{
""streetAddress"": ""21 2nd Street"",
""city"": ""New York"",
""state"": ""FL"",
""postalCode"": ""10021""
},
""phoneNumber"":
[
{
""type"": ""home"",
""number"": ""212 555-1234""
},
{
""type"": ""fax"",
""number"": ""222 222-2222""
},
{
""type"": ""iphone"",
""number"": ""111 111-1111""
}
]
}";
修改2
在考虑了更多有关要求后,我发现更复杂的例子永远不会按原样运作。例如,级联功能无法知道某个电话号码是否已被修改或是否为新电话号码。为了使其工作,每个子实体应具有唯一的标识符。
答案 0 :(得分:18)
使用优秀的JSON.NET library非常容易。此方法将对象与属性(字符串,数字或对象)组合在一起。
public static string Cascade(params string[] jsonArray)
{
JObject result = new JObject();
foreach (string json in jsonArray)
{
JObject parsed = JObject.Parse(json);
foreach (var property in parsed)
result[property.Key] = property.Value;
}
return result.ToString();
}
结果,举个例子:
{
"firstName": "Albert",
"lastName": "Smith",
"phone": "12345"
}
通过调整此解决方案以递归方式工作,您可以合并子对象。以下示例将匹配您的预期结果(数组除外)。您将能够以类似于合并对象(JArray
)的方式轻松扩展此解决方案以合并数组(JObject
)。
public static string Cascade(params string[] jsonArray)
{
JObject result = new JObject();
foreach (string json in jsonArray)
{
JObject parsed = JObject.Parse(json);
Merge(result, parsed);
}
return result.ToString();
}
private static void Merge(JObject receiver, JObject donor)
{
foreach (var property in donor)
{
JObject receiverValue = receiver[property.Key] as JObject;
JObject donorValue = property.Value as JObject;
if (receiverValue != null && donorValue != null)
Merge(receiverValue, donorValue);
else
receiver[property.Key] = property.Value;
}
}
答案 1 :(得分:2)
不是我知道的。对于简单的情况,您可以使用任何JSON库,然后将字典与this one之类的解决方案合并。例如。使用Newtonsoft / Json.NET:
Dictionary<String, String> dict1, dict2, dict3, merged;
dict1 = JsonConvert.DeserializeObject<Dictionary<string,string>>(json1);
dict2 = JsonConvert.DeserializeObject<Dictionary<string,string>>(json2);
dict3 = JsonConvert.DeserializeObject<Dictionary<string,string>>(json3);
merged = Merge(new[]{dict1, dict2, dict3});
显然,在生产代码中,你会将冗余线分解出来。