jq:将对象数组转换为单个对象,并将每个数组索引用作新键

时间:2017-03-09 17:04:08

标签: json google-bigquery jq

我有几个大的json对象(想想GB标度),其中一些最里层的对象值是对象数组。我正在使用jq 1.4而我试图将这些数组分解为单个对象,每个对象都有一个键,例如g__0或g__1,其中数字对应于原始数组中的索引,如返回通过keys函数。每个数组中的对象数量可以任意大(在我的例子中它等于3)。同时我想保留剩下的结构。

对于它的价值,原始结构来自MongoDB,但我无法在此级别更改它。然后,我将使用此json文件为BigQuery创建模式,其中示例列将为seeds.g__1.guid,依此类推。

我有什么:

{
 "port": 4500,
 "notes": "This is an example",
 "seeds": [
  {
    "seed": 12,
    "guid": "eaf612"
  },
  {
    "seed": 23,
    "guid": "bea143"
  },
  {
    "seed": 38,
    "guid": "efk311"
  }
  ]
}

我希望实现的目标:

{
  "port": 4500,
  "notes": "This is an example",
  "seeds": {
    "g__0": {
      "seed": 12,
      "guid": "eaf612"
    },
    "g__1": {
      "seed": 23,
      "guid": "bea143"
    },
    "g__2": {
      "seed": 38,
      "guid": "efk311"
    }
  }
}

谢谢!

2 个答案:

答案 0 :(得分:1)

因此,您基本上希望在BigQuery Table中转置(透视)您的数据,而不是将数据放在行中,如下所示

enter image description here

您的数据如下所示

enter image description here

因此,我的建议是 首先,按原样加载您的数据 所以现在,不要在BigQuery之外进行模式转换,而是在BigQuery中做它!

下面是如何实现您正在寻找的转换的示例(假设您在阵列中有最多三个项目/对象)

#standardSQL
SELECT 
  port, notes, 
  STRUCT(
    seeds[SAFE_OFFSET(0)] AS g__0, 
    seeds[SAFE_OFFSET(1)] AS g__1, 
    seeds[SAFE_OFFSET(2)] AS g__2
  ) AS seeds 
FROM yourTable   

您可以使用CTE(如下所示)使用虚拟数据进行测试

#standardSQL
WITH yourTable AS (
  SELECT 
    4500 AS port, 'This is an example' AS notes,
    [STRUCT<seed INT64, guid STRING>
        (12, 'eaf612'), (23, 'bea143'), (38, 'efk311')
    ] AS seeds
  UNION ALL SELECT 
    4501 AS port, 'This is an example 2' AS notes,
    [STRUCT<seed INT64, guid STRING>
        (42, 'eaf412'), (53, 'bea153')
    ] AS seeds
)
SELECT 
  port, notes, 
  STRUCT(
    seeds[SAFE_OFFSET(0)] AS g__0, 
    seeds[SAFE_OFFSET(1)] AS g__1, 
    seeds[SAFE_OFFSET(2)] AS g__2
  ) AS seeds 
FROM yourTable   

因此,从技术上讲,如果您知道种子数组中的项目/对象的最大数量 - 您可以手动编写所需的SQL语句,以便根据实际数据运行它。 希望你有个主意

当然你可以编写脚本/自动化过程 - 你可以在这里找到类似的旋转任务的例子:

https://stackoverflow.com/a/40766540/5221944
https://stackoverflow.com/a/42287566/5221944

答案 1 :(得分:1)

以下jq程序应该可以解决问题。至少它会为给定的JSON生成所需的结果。该计划是如此简短和直接,我会让它自己说话:

def array2object(prefix):
  . as $in
  | reduce range(0;length) as $i ({}; .["\(prefix)_\($i)"] = $in[$i]);

.seeds |= array2object("g__")