如何用JQ从Graph API响应中构建含UPN与IP的新字典?
解决Graph API告警证据中提取UPN和IP地址的JQ问题
失败原因分析
- 直接遍历evidence数组提取字段:每个证据对象属于单一类型,只有对应类型的字段存在,其他字段都是null,所以遍历后会生成多个包含null的对象,不是你想要的合并结果。
- 单筛选userEvidence:只处理了用户证据类型,没有同时处理IP证据类型,所以IP字段自然为null。
- 同时筛选两类证据:一个证据对象不可能同时是
userEvidence和ipEvidence类型,所以筛选条件逻辑矛盾,返回空数组。
实现方案
核心思路是分别提取不同类型证据的目标字段,再合并成一个统一的对象。这里提供两种可行的JQ写法:
方法一:分别提取后合并
先从evidence数组中筛选出userEvidence类型提取UPN,筛选出ipEvidence类型提取IP,再将两个结果合并为一个对象:
{ upn: (.evidence[] | select(@odata.type == "#microsoft.graph.security.userEvidence") | .userPrincipalName), ipAddress: (.evidence[] | select(@odata.type == "#microsoft.graph.security.ipEvidence") | .ipAddress) }
如果存在多个同类型证据(比如多个IP),可以用first()取第一个结果:
{ upn: (.evidence[] | select(@odata.type == "#microsoft.graph.security.userEvidence") | .userPrincipalName | first), ipAddress: (.evidence[] | select(@odata.type == "#microsoft.graph.security.ipEvidence") | .ipAddress | first) }
方法二:用reduce遍历聚合
通过reduce遍历整个evidence数组,逐步聚合UPN和IP字段,适合后续扩展更多证据类型的场景:
reduce .evidence[] as $item ({}; if $item.@odata.type == "#microsoft.graph.security.userEvidence" then .upn = $item.userPrincipalName elif $item.@odata.type == "#microsoft.graph.security.ipEvidence" then .ipAddress = $item.ipAddress else . end )
内容的提问来源于stack exchange,提问作者createchange
相关产品推荐
相关产品推荐

