使用jq展平/规范化json对象数组

使用jq展平/规范化json对象数组,json,relational-database,jq,Json,Relational Database,Jq,我有一个大型json对象数组。每个对象包含一个foreignKeyId、一个url、一个urlMirror1、一个urlMirror2 以下是一个示例: [ { "foreignKeyId": 1, "url": "https://1-url.com" }, { "foreignKeyId": 2, "url": "https://2-url.

我有一个大型json对象数组。每个对象包含一个
foreignKeyId
、一个
url
、一个
urlMirror1
、一个
urlMirror2

以下是一个示例:

[
  {
    "foreignKeyId": 1,
    "url": "https://1-url.com"
  },
  {
    "foreignKeyId": 2,
    "url": "https://2-url.com",
    "urlMirror1": "https://2-url-mirror-1.com",
  },
  {
    "foreignKeyId": 3,
    "url": "https://3-url.com",
    "urlMirror1": "https://3-url-mirror-1.com",
    "urlMirror2": "https://3-url-mirror-2.com"
  }
}
我想将此json规范化为如下内容:

[
  {
    "foreignKeyId": 1,
    "primariness": 1,
    "url": "https://1-url.com"
  },
  {
    "foreignKeyId": 2,
    "primariness": 1,
    "url": "https://2-url.com",
  },
  {
    "foreignKeyId": 2,
    "primariness": 2,
    "url": "https://2-url-mirror-1.com",
  },
  {
    "foreignKeyId": 3,
    "primariness": 1,
    "url": "https://3-url.com"
  },
  {
    "foreignKeyId": 3,
    "primariness": 2,
    "url": "https://3-url-mirror-1.com",
  },
  {
    "foreignKeyId": 3,
    "primariness": 3,
    "url": "https://3-url-mirror-2.com"
  }
}
使用
jq
有没有这样的方法?如果没有,有没有其他建议可以在不编写太多自定义代码的情况下快速完成此任务?这只需要运行一次,因此任何类型的黑客一次性解决方案都可以工作(bash脚本等)

谢谢

更新:
primariness
应该从键名派生(
url
=>
1
urlMirror1
=>
2
urlMirror2
=>
3
。任何给定对象中键的顺序都是无关紧要的。镜像的数量是固定的(例如,从来没有
urlMirror3
).

这是一个简单的脚本,带有镜像数和原始数的硬编码。希望它能起到作用

jq '
    map(
        { foreinKeyId } +
        (
            { primariness: 1, url },
            (.urlMirror1 // empty | { primariness: 2, url: . }),
            (.urlMirror2 // empty | { primariness: 3, url: . })
        )
    )
' input.json

鉴于OP将查询从泛型限制到更具体的标准,因此@luciole75w提供的答案是最好的(最有可能),请参考该答案

现在,对于@oguzismail来说,这是一种通用的
jtc
方法(它将处理任意数量的
“urlmirr”s
),由3个JSON转换步骤(更新的解决方案)组成:

2.现在插入
“primariness”:N
基于
foreignKeyId
出现索引的记录:

<file.json jtc -w'<foreignKeyId>l:<f>v[-1]<urlM>L:<u>v[^0]' \
               -i'{"url":{{u}},"foreignKeyId":{f}}' /\
               -w'[foreignKeyId]:<f>q:<p:0>v[^0][foreignKeyId]:<f>s:[-1]<p>I1' \
               -i'{"primeriness":{{p}}}' -tc
[
   { "foreignKeyId": 1, "primeriness": 1, "url": "https://1-url.com" },
   { "foreignKeyId": 2, "primeriness": 1, "url": "https://2-url.com", "urlMirror1": "https://2-url-mirror-1.com" },
   { "foreignKeyId": 3, "primeriness": 1, "url": "https://3-url.com", "urlMirror1": "https://3-url-mirror-1.com", "urlMirror2": "https://3-url-mirror-2.com" },
   { "foreignKeyId": 2, "primeriness": 2, "url": "https://2-url-mirror-1.com" },
   { "foreignKeyId": 3, "primeriness": 2, "url": "https://3-url-mirror-1.com" },
   { "foreignKeyId": 3, "primeriness": 3, "url": "https://3-url-mirror-2.com" }
]
bash $ 

这里有一个通用的解决方案,即,它将处理任意多个URLmirror

为了清楚起见,让我们首先定义一个helper函数,该函数为单个输入对象发出{foreignKeyId,primariness,url}对象流:

def primarinesses:
  {foreinKeyId} +
    ({primariness:1, url},
     (to_entries[]
      | (.key | capture( "^urlMirror(?<n>[0-9]+)")) as $n
      | {primariness: ($n.n | tonumber + 1), url : .value } )) ;
也可以用较少的标点符号书写,如下所示:

map(primarinesses)

这是一个很好的问题,非常有趣。但是不清楚键的顺序(
foreinKeyId
url
urlMirror1
urlMirror2
)是可靠的,还是应该从键名(例如
urlMirror1
->2,
urlMirrorN
->N+1)中解析出主键的顺序;或者可以对键名进行硬编码(
urlMirror1
urlMirror2
)在JQ程序中。同意@oguzismail,非常好的JSON查询。如果您感兴趣,我还可以使用
jtc
工具提供此查询的替代解决方案。@Dmitry,不确定OP,但我想看看如何使用jtc处理此问题。我已经编写了两个JQ程序,但它们都很长,无法为类似的我们扩展“e案例。@oguzismail,让我们等到JQ得到认可的答案,然后我会发布jtcversion@oguzismail,我刚刚在问题底部的更新中回答了你的问题。谢谢。Oguz,你能帮我个忙吗?我很想看看JQ(通用)您提出的版本。我写的版本与公认的答案相同,我停止了通用版本的工作,因为OP澄清了:/Peter可能会发布一个简洁的版本,但我会按照问题进行操作。@Dmitry-FYPI(?)优雅:)(y)
def primarinesses:
  {foreinKeyId} +
    ({primariness:1, url},
     (to_entries[]
      | (.key | capture( "^urlMirror(?<n>[0-9]+)")) as $n
      | {primariness: ($n.n | tonumber + 1), url : .value } )) ;
[.[] | primarinesses]
map(primarinesses)