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

3

我有几个大型的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"
  }
  ]
}

What I am hoping to achieve:

{
  "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个回答

2
以下jq程序应该可以达到目的。至少对于给定的JSON,它产生了所需的结果。这个程序非常简短和直接,我会让它自己说明:
def array2object(prefix):
  . as $in
  | reduce range(0;length) as $i ({}; .["\(prefix)_\($i)"] = $in[$i]);

.seeds |= array2object("g__")

谢谢您的建议,我已经尝试了几种不同的情况,它总是表现得很好。 - adaris

1

因此,您基本上想要在BigQuery表中转置(旋转)数据,以便不是像下面的行数据

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://dev59.com/alkR5IYBdhLWcg3w1wgh#40766540
https://stackoverflow.com/a/42287566/5221944


非常感谢你的回复,Mikhail。我没有选择你的答案,因为在我的情况下,很难知道数组中项/对象的最大数量(我还有任意数量的这样的数组),所以我觉得操作行数据更可取。不过我同意在BigQuery级别上这是个好方法。 - adaris

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