You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何使用jq筛选含嵌套键与列表的JSON对象并保留指定键

问题描述

假设我有如下JSON对象:

{
  "a": 1,
  "b": 2,
  "c": [
    {
      "d": 1,
      "e": 2
    },
    {
      "d": 2,
      "e": 3
    }
  ]
}

我希望仅提取一组可能为嵌套类型的键,路径格式例如.a和.c[].d,最终得到如下输出结果:

{
  "a": 1,
  "c": [
    {
      "d": 1
    },
    {
      "d": 2
    }
  ]
}

请问该如何实现上述需求?

实现方案

核心逻辑分为路径解析、递归过滤两个环节:

  • 路径解析:将输入的.c[].d类路径字符串拆分为分层访问标记,比如把.c[].d解析为['c', '*', 'd'],其中*代表需要遍历数组下的所有元素
  • 递归过滤:从根节点开始遍历原始JSON结构,仅保留路径命中的字段:
    • 遇到普通对象时,只保留当前路径层声明过的键,再向下递归处理对应子字段
    • 遇到数组时,遍历所有数组元素,按数组对应的下一层路径规则递归处理每个元素
    • 走到路径末尾时直接返回当前的基础类型值即可

以下是可直接运行的JavaScript实现:

function extractByPaths(source, paths) {
  // 预处理输入路径,拆分为分层访问段
  const parsedPaths = paths.map(path => {
    const segments = []
    path.replace(/^\./, '').split('.').forEach(seg => {
      if (seg.endsWith('[]')) {
        segments.push(seg.slice(0, -2))
        segments.push('*')
      } else {
        segments.push(seg)
      }
    })
    return segments
  })

  // 递归提取核心方法
  function recursiveExtract(currentVal, depth, validPaths) {
    const activePaths = validPaths.filter(p => p.length > depth)
    if (activePaths.length === 0) return undefined

    // 处理数组类型
    if (Array.isArray(currentVal)) {
      return currentVal.map(item => {
        const arrayPaths = activePaths.filter(p => p[depth] === '*')
        return recursiveExtract(item, depth + 1, arrayPaths)
      }).filter(item => item !== undefined)
    }

    // 处理对象类型
    if (typeof currentVal === 'object' && currentVal !== null) {
      const result = {}
      const keyRelatedPaths = {}
      activePaths.forEach(p => {
        const currentKey = p[depth]
        if (currentKey === '*') return
        if (!keyRelatedPaths[currentKey]) keyRelatedPaths[currentKey] = []
        keyRelatedPaths[currentKey].push(p)
      })

      Object.keys(keyRelatedPaths).forEach(key => {
        if (!(key in currentVal)) return
        const subResult = recursiveExtract(currentVal[key], depth + 1, keyRelatedPaths[key])
        if (subResult !== undefined) result[key] = subResult
      })

      return Object.keys(result).length > 0 ? result : undefined
    }

    // 处理基础类型值,命中路径则返回
    const isHit = activePaths.some(p => p.length === depth + 1)
    return isHit ? currentVal : undefined
  }

  return recursiveExtract(source, 0, parsedPaths)
}

// 测试用例
const source = {
  "a": 1,
  "b": 2,
  "c": [
    {"d": 1, "e": 2},
    {"d": 2, "e": 3}
  ]
}
const result = extractByPaths(source, ['.a', '.c[].d'])
console.log(JSON.stringify(result, null, 2))

上述实现支持多层嵌套路径,比如.a.b.c、.list[].subList[].id这类格式都可以正常处理,运行测试用例即可得到你预期的输出结果。

内容的提问来源于stack exchange,提问作者alon-k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 04:18:15