如何解析数据类型不一致的JSON?

时间:2018-11-14 13:14:44

标签: json bash csv parsing jq

我需要根据以下结构的csv文件创建一个JSON报告(在我认为合适的范围内,对其进行了简化):

{
  "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.item连接到bar_id
  2. 一个或多个foo.item指向一个bar.item
  3. 指向同一foo.item的多个bar.item将具有相同的foo.item.value
  4. 恰好一个var.item指向一个bar.item
  5. 所有项目均按bar_id
  6. 排序
  7. 格式不一致bar.item是一个对象(如果只有一项),否则是一个数组(同样适用于foo.itemvar.item
  8. 我坚持使用这种格式

输出报告:

  1. 处理所有data个对象
  2. 为每个没有具有值bar.item的相应foo.item的{​​{1}}创建报告
  3. 输出格式:foo_bad

我的尝试

我当前使用的临时.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" ,但我更喜欢使用它。

1 个答案:

答案 0 :(得分: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