如何移除JSON Array父级并保留子JSON数组
嘿,我懂你遇上的麻烦了——从SQL Server存储过程拿到的JSON嵌套了一堆没必要的数组层级,搜了半天没找到对应的移除方案对吧?刚好我之前处理过几乎一模一样的场景,给你几个实用的解决办法:
方案1:从SQL Server源头修正(最推荐)
既然JSON是存储过程生成的,最好直接在生成阶段就避免多余的数组。SQL Server的FOR JSON语句如果用了默认的PATH或AUTO模式,很容易给单条结果套上数组壳子。你可以调整存储过程里的JSON生成逻辑:
比如原来的生成代码可能是这样的:
SELECT (SELECT 'kode' AS name, (SELECT value, RankNum FROM YourDiagnosisTable FOR JSON PATH) AS value FOR JSON PATH) AS KODE, -- HEALING字段同理生成 FOR JSON PATH
改成给嵌套的FOR JSON加上WITHOUT_ARRAY_WRAPPER参数,直接去掉多余的数组包裹:
SELECT (SELECT 'kode' AS name, (SELECT value, RankNum FROM YourDiagnosisTable FOR JSON PATH) AS value FOR JSON PATH, WITHOUT_ARRAY_WRAPPER) AS KODE, -- HEALING字段同样加上WITHOUT_ARRAY_WRAPPER FOR JSON PATH, WITHOUT_ARRAY_WRAPPER
这样生成的JSON就会是干净的对象结构,不会有多余的[]包裹。
方案2:应用层代码处理(适合无法修改存储过程的情况)
如果没法动存储过程,就在拿到JSON后用代码扁平化嵌套数组。这里给你两种常用语言的实现:
JavaScript版本
写个递归函数自动处理所有长度为1的数组:
function flattenNestedArrays(obj) { // 如果是数组且只有一个元素,直接取元素递归处理 if (Array.isArray(obj)) { return obj.length === 1 ? flattenNestedArrays(obj[0]) : obj.map(item => flattenNestedArrays(item)); } // 如果是对象,遍历所有属性递归处理 else if (typeof obj === 'object' && obj !== null) { const result = {}; for (const key in obj) { result[key] = flattenNestedArrays(obj[key]); } return result; } // 基本类型直接返回 return obj; } // 用法示例 const rawJson = [{"KODE":[{"name":"kode","value":[{"value":"DIAG001","RankNum":1},{"value":"DIAG002","RankNum":1}]}],"HEALING":[{"name":"Encountrance","value":[...]}]}]; const cleanedJson = flattenNestedArrays(rawJson); console.log(cleanedJson);
C#版本(用Newtonsoft.Json)
using Newtonsoft.Json.Linq; public static JToken FlattenJson(JToken token) { if (token.Type == JTokenType.Array) { var array = (JArray)token; // 数组长度为1则取第一个元素继续处理 if (array.Count == 1) { return FlattenJson(array[0]); } // 数组长度大于1则逐个处理元素 return new JArray(array.Select(FlattenJson)); } else if (token.Type == JTokenType.Object) { var obj = (JObject)token; var result = new JObject(); foreach (var prop in obj.Properties()) { result[prop.Name] = FlattenJson(prop.Value); } return result; } return token; } // 调用示例 var rawJson = "[{\"KODE\":[{\"name\":\"kode\",\"value\":[{\"value\":\"DIAG001\",\"RankNum\":1},...]}],\"HEALING\":[...]}]"; var cleanedToken = FlattenJson(JToken.Parse(rawJson)); var finalJson = cleanedToken.ToString();
方案3:SQL Server事后修正(临时应急用)
如果必须在数据库里处理已生成的JSON,可以用JSON_QUERY和JSON_MODIFY手动移除数组层级:
DECLARE @rawJson NVARCHAR(MAX) = '[{"KODE":[{"name":"kode","value":[{"value":"DIAG001","RankNum":1},...]}],"HEALING":[...]}]'; -- 移除最外层数组 SET @rawJson = JSON_QUERY(@rawJson, '$[0]'); -- 移除KODE字段的数组包裹 SET @rawJson = JSON_MODIFY(@rawJson, '$.KODE', JSON_QUERY(@rawJson, '$.KODE[0]')); -- 移除HEALING字段的数组包裹 SET @rawJson = JSON_MODIFY(@rawJson, '$.HEALING', JSON_QUERY(@rawJson, '$.HEALING[0]')); -- 如果还有内层的value数组需要处理,继续用同样逻辑 SET @rawJson = JSON_MODIFY(@rawJson, '$.KODE.value', JSON_QUERY(@rawJson, '$.KODE.value')); SELECT @rawJson AS CleanedJson;
这个方法适合临时修正,但效率不如从源头生成干净JSON,不建议长期用。
内容的提问来源于stack exchange,提问作者flix
相关产品推荐
相关产品推荐

