【问题标题】:Using jq as a non json formatter使用 jq 作为非 json 格式化程序
【发布时间】:2021-09-28 06:44:04
【问题描述】:

我有一些 json 输入,如下所示:

{
  "vers": "2.0",
  "result": [
    {
      "name": "Petes corner store",
      "address": [
        "LOCKED BAY 222",
        "Sydney",
        "9876"
      ],
      "dbno": "201449",
      "segments": [
        {
          "val": "23.40",
          "lines": [
            {
              "val": "11.40",
              "products": [
                {
                  "name": "Product 1",
                  "qty": "2",
                  "price_ea": "4.62",
                  "extended": "9.24"
                },
                {
                  "name": "Prod desc 2",
                  "qty": "18",
                  "price_ea": "0.12",
                  "extended": "2.16"
                }
              ]
            }
          ]
        },
        {
          "val": "16.00",
          "lines": [
            {
              "val": "16.00",
              "products": [
                {
                  "name": "Product 3",
                  "qty": "3",
                  "price_ea": "4.00",
                  "extended": "12.00"
                }
              ]
            }
          ]
        }  
      ]
    }
  ],
  "id": 1
}

数据具有可变长度的结果、段和线数组。我正在尝试将非 json 输出格式化为:

COMMENT|Petes corner store|201449
SPOT|addr|\@lbl|LOCKED BAY 222|Sydney|9876
TABLE|Product 1|2|4.62|9.24
TABLE|Prod desc 2|18|0.12|2.16
BREAK
TABLE|Product 3|3|4.00|12.00
BREAK
FLUSH

其中 TABLE 条目是提取的段的列表[].lines[].products[] 保持相同的顺序,每个段之间有一个分隔符。我试图使用单个 jq 脚本来完成整个工作,基本上是:

.result |
keys[] as $k |
"COMMENT|\(.[$k] | "\(.name)|\(.dbno)"  )
SPOT|addr|\\@lbl|\(.[$k].address  | join("|") )
TABLE|Cant figure this out...
FLUSH
"

我认为这是学习 jq 的好时机,因为我已经在 bourne shell 中编写了这个,它可以工作,但它不是很优雅。 那么,关于让我的 TABLE 条目正常工作的任何指针?

【问题讨论】:

    标签: json jq


    【解决方案1】:

    根据您的输入,以下 jq 程序会产生与您所期望的结果非常相似的结果:

    .result[0]
    | ["COMMENT", .name, .dbno],
      (["SPOT", "addr", "\\@lbl"] + .address),
      ( .segments[].lines[].products[] as $p
       | ((["TABLE"] + [$p[]]),
          ["BREAK"])),
      ["FLUSH"]
    
    | join("|")
    

    即:

    COMMENT|Petes corner store|201449
    SPOT|addr|\@lbl|LOCKED BAY 222|Sydney|9876
    TABLE|Product 1|2|4.62|9.24
    BREAK
    TABLE|Prod desc 2|18|0.12|2.16
    BREAK
    TABLE|Product 3|3|4.00|12.00
    BREAK
    FLUSH
    

    如果产品详细信息对象中键的顺序可能不同,那么您可能希望指定顺序而不是使用[$p[]]

    【讨论】:

      【解决方案2】:

      非常感谢您花时间回复。

      通过给出的语法提示,我能够创建一个完全符合我要求的脚本。它仅在每个线阵列之后正确设置 BREAK 行,并且它将与阵列中的多个 .result 记录一起使用。

      .result
      | keys[] as $c
      |
        ["COMMENT", (.[$c] | "\(.name), \(.dbno)" )],
        ["SPOT", "addr","\\@lbl"] + (.[$c].address),
        (
          (.[$c].segments | keys[]) as $s |
            (.[$c].segments[$s].lines | keys[]) as $l |
              (.[$c].segments[$s].lines[$l].products | keys[]) as $p |
                (if $p > 0 then ["BREAK"] else empty end),
                [
                  "TABLE",
                  .[$c].segments[$s].lines[$l].products[$p].name,
                  .[$c].segments[$s].lines[$l].products[$p].qty,
                  .[$c].segments[$s].lines[$l].products[$p].price_ea,
                  .[$c].segments[$s].lines[$l].products[$p].extended
                  ]
        ),
      ["FLUSH"]
      | join("|")
      

      可能会进行一些优化,但这给了我一个很好的工作立足点。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-07-07
        • 1970-01-01
        • 1970-01-01
        • 2017-01-01
        • 2021-03-10
        相关资源
        最近更新 更多