基于SCIM API使用attributes和excludedAttributes编辑JSON的通用方案
通用解决方案:SCIM API中使用
attributes/excludedAttributes编辑JSON响应 先从你给出的具体场景入手,直观理解需求:
原始响应:
{ "emails": [ { "type": "work", "value": "bjensen@example.com" } ], "id": "2819c223-7f76-453a-919d-413861904646", "phoneNumbers": [ { "type": "work", "value": "555-555-8377" }, { "type": "business", "value": "555-555-8377" } ], "schemas": [ "urn:scim:schemas:core:1.0" ], "userName": "bjensen" }
当传入参数 excludedAttributes=phoneNumbers.type 时,期望得到的过滤后响应:
{ "emails": [ { "type": "work", "value": "bjensen@example.com" } ], "id": "2819c223-7f76-453a-919d-413861904646", "phoneNumbers": [ { "value": "555-555-8377" }, { "value": "555-555-8377" } ], "schemas": [ "urn:scim:schemas:core:1.0" ], "userName": "bjensen" }
下面是适配所有SCIM场景的通用实现思路,核心是处理属性路径解析与嵌套结构的递归过滤:
1. 解析属性参数
不管是attributes(指定保留属性)还是excludedAttributes(指定排除属性),第一步要把参数转成可遍历的层级路径:
- 先分割逗号分隔的参数值,比如
excludedAttributes=phoneNumbers.type,emails.type会拆成["phoneNumbers.type", "emails.type"] - 再把每个路径拆成层级节点数组,比如
phoneNumbers.type拆成["phoneNumbers", "type"],方便后续遍历嵌套JSON结构
2. 递归遍历并过滤JSON
需要写一个递归函数处理对象和数组两种核心结构:
- 处理对象:遍历每个键,判断当前键对应的路径是否符合保留/排除规则。如果是排除规则匹配则跳过该键;如果是包含规则,只有匹配的键才保留。
- 处理数组:对数组中的每个元素递归调用过滤函数——毕竟SCIM里的数组元素大多是嵌套对象(比如
phoneNumbers的每个条目),得逐个处理内部属性。
3. 遵循SCIM规范的参数优先级
根据SCIM官方规范,attributes的优先级高于excludedAttributes:
- 如果同时传入两个参数,先按
attributes保留指定属性,再在这个结果上应用excludedAttributes做二次排除 - 如果只传
attributes,仅保留指定路径的所有层级属性 - 如果只传
excludedAttributes,保留所有属性除了指定路径的属性
4. 简化实现示例(JavaScript)
这里给一个可直接参考的代码片段,你可以根据自己的技术栈调整:
function filterSCIMResponse(data, attributes = [], excludedAttributes = []) { // 把参数路径解析为层级数组 const parsePaths = (paths) => paths.map(path => path.split('.')); const attrPaths = parsePaths(attributes); const excludePaths = parsePaths(excludedAttributes); // 递归过滤核心函数 const filterNode = (node, currentPath = []) => { if (Array.isArray(node)) { return node.map(item => filterNode(item, currentPath)); } if (typeof node !== 'object' || node === null) { return node; } const filteredObj = {}; Object.keys(node).forEach(key => { const newPath = [...currentPath, key]; // 判断是否符合包含规则(若传入了attributes) const isIncluded = attributes.length === 0 || attrPaths.some(path => { return path.slice(0, newPath.length).join('.') === newPath.join('.'); }); // 判断是否符合排除规则 const isExcluded = excludePaths.some(path => { return path.join('.') === newPath.join('.'); }); if (isIncluded && !isExcluded) { filteredObj[key] = filterNode(node[key], newPath); } }); return filteredObj; }; return filterNode(data); } // 使用示例 const originalResponse = { /* 你的原始SCIM响应数据 */ }; const filteredResult = filterSCIMResponse(originalResponse, [], ['phoneNumbers.type']); console.log(filteredResult);
额外注意事项
- 要兼容SCIM中的多层嵌套属性,比如
name.givenName这类深层路径 - 处理数组时要注意空数组、非对象数组的边界情况
- 严格遵循SCIM规范的参数优先级,避免逻辑冲突
内容的提问来源于stack exchange,提问作者Bush
相关产品推荐
相关产品推荐

