【问题标题】:How to parse JSON with an inconsistent data type?如何解析具有不一致数据类型的 JSON?
【发布时间】:2019-04-17 11:21:14
【问题描述】:

我需要从具有以下结构的JSON 文件创建csv 报告(尽可能简化):

{
  "data": [
    {
      "id": "123",
      "foo": {
        "item": {
          "value": "foo_good",
          "bar_id": "1"
        }
      },
      "bar": {
        "item": {
          "id": "1",
          "value": "bar_value_1a"
        }
      },
      "var": {
        "item": {
          "value": "var_value_1a",
          "bar_id": "1"
        }
      }
    },
    {
      "id": "456",
      "foo": {
        "item": [
          {
            "value": "foo_bad",
            "bar_id": "1"
          },
          {
            "value": "foo_good",
            "bar_id": "2"
          },
          {
            "value": "foo_good",
            "bar_id": "2"
          },
          {
            "value": "foo_bad",
            "bar_id": "3"
          },
          {
            "value": "foo_good",
            "bar_id": "4"
          }
        ]
      },
      "bar": {
        "item": [
          {
            "id": "1",
            "value": "bar_value_2a"
          },
          {
            "id": "2",
            "value": "bar_value_2b"
          },
          {
            "id": "3",
            "value": "bar_value_2c"
          },
          {
            "id": "4",
            "value": "bar_value_2d"
          }
        ]
      },
      "var": {
        "item": [
          {
            "value": "var_value_2a",
            "bar_id": "1"
          },
          {
            "value": "var_value_2b",
            "bar_id": "2"
          },
          {
            "value": "var_value_2c",
            "bar_id": "3"
          },
          {
            "value": "var_value_2d",
            "bar_id": "4"
          }
        ]
      }
    }
  ]
}

数据结构:

  1. foo.itemvar.item 连接到 bar.itembar_id
  2. 一个或多个foo.item指向一个bar.item
  3. 多个foo.item指向同一个bar.item将有相同的foo.item.value
  4. 恰好一个var.item指向一个bar.item
  5. 所有项目均按bar_id排序
  6. 格式不一致。如果只有一项,bar.item 是一个对象,否则它是一个数组(也适用于 foo.itemvar.item
  7. 我被这种格式卡住了

输出报告:

  1. 处理所有data对象
  2. 为每个具有任何对应foo.item 且值为foo_badbar.item 创建报告
  3. 输出格式:.id, .bar.item.value, .var.item.value

我的尝试:

我目前使用的临时 jq 脚本丢弃了多个 bar.item 等,并仅创建了对真实数据的估计:

.data[]
| .foo.item |= if type=="array" then .[0] else . end
| .bar.item |= if type=="array" then .[0] else . end
| .var.item |= if type=="array" then .[0] else . end
| select(.foo.item.value != "foo_bad")
| [.id,.bar.item.value,.var.item.value]
| @csv

输出如下:

"123","bar_value_1a","var_value_1a"

期望的输出:

"123","bar_value_1a","var_value_1a"
"456","bar_value_2b","var_value_2b"
"456","bar_value_2d","var_value_2d"

我更喜欢使用jq,尽管我并不坚持。

【问题讨论】:

    标签: json bash csv parsing jq


    【解决方案1】:

    我建议您首先确保 .foo.item、.bar.item 和 .var.item 始终是数组。这可以使用以下辅助函数来完成:

    def w: if type=="array" then . else [.] end;
    

    您的 jq 过滤器将如下开始:

    .data[]
    | .foo.item |= w
    | .bar.item |= w
    | .var.item |= w
    

    接下来你要做什么取决于你想对所有这些数组做什么,但我已经验证了以下会产生你想要的结果:

    .data[]
    | .foo.item |= w
    | .bar.item |= w
    | .var.item |= w
    | range(0; .foo.item | length) as $i
    | select(.foo.item[$i].value != "foo_bad")
    | select(.bar.item[$i].value)
    | [.id,.bar.item[$i].value,.var.item[$i].value]
    | @csv
    

    【讨论】:

    • 嗯嗯,因为可以有更多的foo.item指向同一个bar.item,我不认为这种方法似乎依赖于一个foo.item指向一个bar.item将工作。例如,通过将第二个data 对象中的第四个foo.item 更改为foo_bad,您的代码将产生不希望的结果。也许我的问题不够清楚? :) 但是谢谢,无论如何,您的代码为我指明了正确的方向。辅助函数使代码更具可读性!
    • 正如我所指出的,我不了解您的实际要求。我猜你会想要添加range(0; .bar.item | length) as $j 和/或range(0; .var.item | length) as $k
    • 我只是不想包含具有 any foo.items 且值 foo_bad 指向它们的 bar.items。因此,如果我将第二个data 对象中的第四个foo.item 更改为foo_bad,我不希望bar.item 的报告与id 等于3。现在可能更清楚了吗? :) 我知道输入数据相当大,因此感谢您的努力。
    • 所以...我忘了提一件重要的事情:如果有更多的foo.items 指向同一个bar.item,那么它们都将具有相同的foo.item.value。所以只需添加| .foo.item |= unique_by(.bar_id) 即可解决问题。我将编辑我的要求,您可以编辑您的问题。我很乐意接受它作为解决方案。再次感谢。
    猜你喜欢
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-12-09
    • 1970-01-01
    • 2021-03-06
    • 2017-03-15
    相关资源
    最近更新 更多