【问题标题】:How can I transform a list of Objects to a formatted String with object Fields using JQ如何使用 JQ 将对象列表转换为带有对象字段的格式化字符串
【发布时间】:2021-05-22 10:07:56
【问题描述】:

我有一个如下的 JSON 数组:

    [
      {
        "key" : "Name",
        "value" : "John"
      }, 
      { 
        "key" : "City",
        "value" : "New York"
       },
      {
        "key" : "Country",
        "value" : "USA"
      }
    ]

我需要将其转换为如下所示的字符串:

--metadata "key": "Name", "value" : "John" --metadata "key": "City", "value" : "New York" --metadata "key": "Country", "value" : "USA"

这将是 python 脚本中命令的输入。

我尝试了一些东西,但没有运气:

  1. 我正在尝试使用映射函数进行转换,但我不确定如何为单词键和值转义 ",因此这会中断并尝试在此之后应用连接,但出现错误。

    。 |map({"-- 元数据键": .key, "value" : .value})

输出:

[
  {
    "-- metadata key": "Name",
    "value": "John"
  },
  {
    "-- metadata key": "City",
    "value": "New York"
  },
  {
    "-- metadata key": "Country",
    "value": "USA"
  }
]

如果我将join(' ') 附加到上述查询中,则会引发以下错误:

jq: error: syntax error, unexpected INVALID_CHARACTER (Unix shell quoting issues?) at <top-level>, 

我对 JQ 很陌生,所以可能没有足够的知识来应用其他功能,任何帮助和解释都会很有用。

【问题讨论】:

  • (作为评论发布,因为我没有时间解释它是如何工作的)你在寻找类似this 的东西吗?
  • 我很好奇——您是否为您可能遇到的每一类问题创建了一个单独的用户帐户? (“techQueriesJQ JQ”是一个相当不寻常的名称选择)。请注意,将您的存在分散到多个帐户意味着您建立声誉的速度较慢,因此与使用单个共享帐户相比,您在网站上拥有的权限更少。
  • 感谢 Charles 的提醒。会照顾的。
  • 只需要在结果字符串的开头和结尾删除“”,而不需要删除其他“”,如键、值。

标签: arrays json jq transformation


【解决方案1】:

这是一个快速而肮脏的例子:

$ jq -r '.[] | "--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\""' so8247.json | awk 'ORS=" "'
--metadata "key": "Name", "value": "John" --metadata "key": "City", "value": "New York" --metadata "key": "Country", "value": "USA"

(编辑:请参阅下文了解如何在没有awk 的情况下执行此操作)

.[] 位只是循环遍历数组的元素; map(x) 等同于 [.[] | x] 所以这几乎是一样的,只是没有将结果放入我们不想要的数组中。

其余部分只是创建您感兴趣的字符串。您可以使用\(x) 将更多 JQ 放入字符串中间。没有 '-r' 和 awk 的输出将如下所示:

$ jq '.[] | "--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\""' so8247.json
"--metadata \"key\": \"Name\", \"value\": \"John\""
"--metadata \"key\": \"City\", \"value\": \"New York\""
"--metadata \"key\": \"Country\", \"value\": \"USA\""

-r”去掉了所有额外的引用:

$ jq -r '.[] | "--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\""' so8247.json
--metadata "key": "Name", "value": "John"
--metadata "key": "City", "value": "New York"
--metadata "key": "Country", "value": "USA"

awk 将其合并为一行。

使用map 可以得到几乎相同的东西,用数组包裹:

$ jq -r 'map("--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\"")' so8247.json
[
  "--metadata \"key\": \"Name\", \"value\": \"John\"",
  "--metadata \"key\": \"City\", \"value\": \"New York\"",
  "--metadata \"key\": \"Country\", \"value\": \"USA\""
]

这很容易剥离:

$ jq -r 'map("--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\"") | .[]' so8247.json
--metadata "key": "Name", "value": "John"
--metadata "key": "City", "value": "New York"
--metadata "key": "Country", "value": "USA"

通过awk,你就完成了:

$ jq -r 'map("--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\"") | .[]' so8247.json | awk 'ORS=" "'
--metadata "key": "Name", "value": "John" --metadata "key": "City", "value": "New York" --metadata "key": "Country", "value": "USA"

注意:显然我不知道如何在纯 JQ 中执行 awk 位;如果可能的话,希望有人会告诉我们如何做到这一点。

编辑:我刚刚看到@oguz ismail 的评论;使用mapjoin 可以消除对awk 的需求:

$ jq -r 'map("--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\"") | join(" ")' so8247.json
--metadata "key": "Name", "value": "John" --metadata "key": "City", "value": "New York" --metadata "key": "Country", "value": "USA"

编辑:使用 Charles Duffy 从使用 '-j' 的评论中提出的使用建议来消除 mapjoinawk

$ jq -j '.[] | "--metadata \"key\": \"\(.key)\", \"value\": \"\(.value)\""' so8247.json
--metadata "key": "Name", "value": "John"--metadata "key": "City", "value": "New York"--metadata "key": "Country", "value": "USA"

【讨论】:

  • 考虑从jq -r 切换到jq -j,这将抑制每条记录后的自动换行符,以消除对awk 的需要同时仍然流式输出一个元素时间,因此比map+join 方法更有效。
【解决方案2】:

您可以结合 jq 和 bash 脚本来获得预期的结果:

#!/usr/bin/env bash

declare -a pyargs
while read -r line; do
    pyargs+=(--metadata "$line")
done < <(jq -r '.[]|"\"key\": \"\(.key)\", \"value\": \"\(.value)\""' json-input)

python "${pyargs[@]}"

【讨论】:

  • @CharlesDuffy 谢谢,你会怎么输入--metadata
  • 在我的例子中,我不能放置一个 bash 脚本——我需要创建一个 JQ 命令并输入一个不同的处理器来执行 jq。
  • 对不起,我错过了那部分。是的,这个循环仍然是现代 bash 的正确选择。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-02-25
  • 1970-01-01
相关资源
最近更新 更多