如何在JSON-LD中查找顶层对象?能否通过框架提取其ID?
基于JSON-LD API 1.1提取顶层对象ID的方法
核心逻辑
顶层对象指仅包含自引用或无任何外部引用的对象,本质是找出未被其他对象(除自身外)引用的节点。
步骤一:标准化JSON-LD结构
先用JSON-LD API的expand()方法统一结构,不管输入是对象数组还是带@graph的结构,最终都会转为包含@graph的标准化格式,方便后续统一处理。
// 示例:标准化输入结构 const expanded = await jsonld.expand(inputJsonLd); // 取出图节点集合,兼容无@graph的场景 const graph = expanded[0]['@graph'] || [];
步骤二:收集所有外部引用ID
遍历图中每个对象,提取所有指向其他节点的引用(即值为{"@id": "xxx"}的属性),同时排除自引用(引用自身ID的情况),最终得到一个被外部引用的ID集合。
const referencedIds = new Set(); graph.forEach(node => { const nodeId = node['@id']; // 遍历当前节点的所有属性值 Object.values(node).forEach(value => { // 处理单个引用节点 if (typeof value === 'object' && value !== null && '@id' in value) { if (value['@id'] !== nodeId) { referencedIds.add(value['@id']); } } // 处理引用节点数组 else if (Array.isArray(value)) { value.forEach(item => { if (typeof item === 'object' && item !== null && '@id' in item) { if (item['@id'] !== nodeId) { referencedIds.add(item['@id']); } } }); } }); });
步骤三:筛选顶层对象
遍历图中所有节点,只要节点的@id不在被外部引用的ID集合里,就是符合要求的顶层对象。如果输入包含多个独立@graph,需对每个图单独执行上述步骤,避免跨图引用干扰结果。
// 筛选顶层对象 const topLevelNodes = graph.filter(node => !referencedIds.has(node['@id'])); // 提取顶层对象的ID列表 const topLevelIds = topLevelNodes.map(node => node['@id']);
用JSON-LD框架(Framing)实现
也可以结合框架快速提取,先通过上述步骤生成被引用ID列表,再构造框架排除这些ID:
// 构造框架:仅保留未被外部引用的节点 const frame = { "@type": "*", "@explicit": true, "@not": { "@id": Array.from(referencedIds) } }; const framedResult = await jsonld.frame(expanded, frame); const topLevelIdsFromFrame = framedResult['@graph'].map(node => node['@id']);
注意事项
- 若输入包含多个独立
@graph,必须分图处理,否则会把跨图的引用误判为内部引用; - 自引用的情况已在步骤二中被排除,最终结果完全符合“仅自引用或无引用”的顶层对象定义;
- 需覆盖所有可能的引用场景,比如嵌套在数组中的引用、不同属性下的引用节点。
内容的提问来源于stack exchange,提问作者Kaj Kandler
相关产品推荐
相关产品推荐

