jq: 去除不必要的嵌套层级来扁平化对象

3
我遇到了一个问题,即json文件中同一个键有时具有平面值,而其他情况下它具有额外的嵌套层次(对于我的目的来说是不必要的),然后包括相关的值。
该文件按换行符分隔,我正在尝试摆脱任何额外的层次。到目前为止,我只能在树的第一级出现嵌套层次的情况下做到这一点,使用以下方法:
jq -c '[.] | map(.[] |= if type == "object" and (.number | length) > 0 then .numberLong else . end) | .[]' mongoDB.json

下面的示例进一步说明了这一点。我最初所拥有的是:
  {
    "name": "John",
    "age": {
        "numberLong": 22
      }
  }
  {
    "name": "Jane",
    "age": 24
  }
  {
    "name": "Dennis",
    "age": 34,
    "details": [
      {
        "telephone_number": 555124124
      }
    ]
  }
  {
    "name": "Frances",
    "details": [
      {
        "telephone_number": {
            "numberLong": 444245523
          }
      }
    ]
  }

我的脚本所做的事情(第二个numberLong被忽略):
  {
    "name": "John",
    "age": 22
  },
  {
    "name": "Jane",
    "age": 24
  }
  {
    "name": "Dennis",
    "age": 34,
    "details": [
      {
        "telephone_number": 555124124
      }
    ]
  }
  {
    "name": "Frances",
    "details": [
      {
        "telephone_number":  {
            "numberLong": 444245523
          }
      }
    ]
  }

我实际上希望达到的目标是(递归复制所有 numberLong 键的值到上一级,无论它们在文件中的位置):
[
  {
    "name": "John",
    "age": 22
  },
  {
    "name": "Jane",
    "age": 24
  },
  {
    "name": "Dennis",
    "age": 34,
    "details": [
      {
        "telephone_number": 555124124
      }
    ]
  },
  {
    "name": "Frances",
    "details": [
      {
        "telephone_number": 444245523
      }
    ]
  }
]

这个转换是日常流程的一部分,并且适用于多个文件,文件大小可达70GB,因此在遍历文件时速度可能成为一个潜在问题。问题源于MongoDB的不同类型:MongoDB中NumberLong和简单整数之间的差异?谢谢!
1个回答

3
如果您的jq具有'walk/1',那么最简单的完全通用解决方案将如下所示:
walk( if type=="object"
      then with_entries( if .value | (type == "object" and has("numberLong"))
                         then .value |= .numberLong
                         else . end)
      else . end )

如果你的jq没有'walk',那最好升级一下,因为这也会提高速度;否则,你可以在谷歌上搜索它在jq中的定义。
如果对于非常大的文件来说速度太慢了,你可能需要跟踪确切的位置,避免完全通用方法的开销。
处理非常大的文件的注意事项:
你的示例("What I have initially")给出了一系列对象,所以值得指出的是,由于jq是面向流的,它处理由不是很大的JSON实体(也称为"文档")组成的流的大型文件时没有问题。
(一个近似的经验法则是,如果输入中最大的JSON实体大小为N个单位,如果由jq创建的最大的JSON实体大小为M个单位,则jq可能需要访问约M + N + max(M,N)个单位的内存。)
为了处理包含单个JSON数组的非常大的文件,建议先生成顶层元素的流进行后续处理。
在最坏的情况下(一个非常大的文件,其中一个非常大的、复杂的JSON文档),你可能需要使用像jq这样的流解析器。
有关处理非常大的文件的各种技术示例,请参见使用jq处理巨大的GEOJson文件

1
当前定义可以在builtin.jq第283行找到。 - Thor

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接