使用JSON.net合并JSON时空对象未覆盖原对象的问题
问题:Json.NET合并时空对象无法覆盖原对象
我用Json.NET写了一段合并完整JSON和部分JSON的代码,遇到空对象场景时不符合预期:
代码示例
string jsonOrigen = @" { 'business': { 'tradingaccount': [ '60325f59-6bef-418a-69a1-08db40bce9af', '054ae632-9b82-4644-6e8c-08db45721efd' ], 'campaign': [ 'cf308053-3118-4e92-7bb7-08db73cba4df', '5ad21da9-337a-4afc-7bb8-08db73cba4df' ], 'service': [ 'ab14b586-38d8-41a2-01d4-08db86a59448', 'adac9392-d602-4874-01d5-08db86a59448' ] } }"; string jsonParcial = @"{ 'business': {} }"; JObject tokenOrigen = JObject.Parse(jsonOrigen); JObject tokenParcial = JObject.Parse(jsonParcial); tokenOrigen.Merge(tokenParcial, new JsonMergeSettings { MergeNullValueHandling = MergeNullValueHandling.Merge }); string res = tokenOrigen.ToString(Formatting.Indented);
预期输出
"business": {}
实际输出
{ "business": { "tradingaccount": [ "60325f59-6bef-418a-69a1-08db40bce9af", "054ae632-9b82-4644-6e8c-08db45721efd" ], "campaign": [ "cf308053-3118-4e92-7bb7-08db73cba4df", "5ad21da9-337a-4afc-7bb8-08db73cba4df" ], "service": [ "ab14b586-38d8-41a2-01d4-08db86a59448", "adac9392-d602-4874-01d5-08db86a59448" ] } }
原因分析
Json.NET的Merge方法默认逻辑是合并对象的属性,空对象{}没有任何属性,所以不会对原对象的属性做修改。MergeNullValueHandling.Merge仅针对null值生效,空对象不属于null,因此无法触发覆盖行为。
解决方案
方法1:手动检查并替换空对象
遍历部分JSON的属性,若属性值是空JObject,直接替换原对象的对应属性,而不是用Merge:
string jsonOrigen = @" { 'business': { 'tradingaccount': [ '60325f59-6bef-418a-69a1-08db40bce9af', '054ae632-9b82-4644-6e8c-08db45721efd' ], 'campaign': [ 'cf308053-3118-4e92-7bb7-08db73cba4df', '5ad21da9-337a-4afc-7bb8-08db73cba4df' ], 'service': [ 'ab14b586-38d8-41a2-01d4-08db86a59448', 'adac9392-d602-4874-01d5-08db86a59448' ] } }"; string jsonParcial = @"{ 'business': {} }"; JObject tokenOrigen = JObject.Parse(jsonOrigen); JObject tokenParcial = JObject.Parse(jsonParcial); // 遍历部分JSON的属性,处理空对象覆盖 foreach (var prop in tokenParcial.Properties()) { if (prop.Value is JObject jObj && !jObj.HasValues) { // 空对象,直接替换原对象的属性 tokenOrigen[prop.Name] = prop.Value; } else { // 非空对象,正常合并 tokenOrigen.Merge(prop.Value, new JsonMergeSettings { MergeNullValueHandling = MergeNullValueHandling.Merge }); } } string res = tokenOrigen.ToString(Formatting.Indented);
方法2:自定义合并逻辑(支持嵌套场景)
如果需要处理嵌套的空对象覆盖,可以写递归方法实现:
public static void MergeWithEmptyObjectOverwrite(JObject target, JObject source, JsonMergeSettings settings) { foreach (var prop in source.Properties()) { if (prop.Value is JObject sourceObj && !sourceObj.HasValues) { target[prop.Name] = sourceObj; } else if (prop.Value is JObject sourceNested && target[prop.Name] is JObject targetNested) { // 嵌套对象,递归处理 MergeWithEmptyObjectOverwrite(targetNested, sourceNested, settings); } else { // 其他类型,正常合并 target.Merge(prop.Value, settings); } } } // 使用方式 MergeWithEmptyObjectOverwrite(tokenOrigen, tokenParcial, new JsonMergeSettings { MergeNullValueHandling = MergeNullValueHandling.Merge });
运行修改后的代码,就能得到预期的"business": {}结果。
内容的提问来源于stack exchange,提问作者Kiquenet
相关产品推荐
相关产品推荐

