繁体   English   中英

如何使用jq从json创建具有可变数组长度的csv

[英]How to make a csv from json with variable array lengths using jq

我有一个具有以下格式的JSON

{
    "type": "conversation",
    "id": "1234",
    "created_at": 1425586662,
    "initial_message": {
        "type": "initial_message",
        "id": "567",
        "body": "<p>Testing</p>",
        "author": {
            "type": "admin",
            "id": "9382"
        }
    },
    "conversation_parts": {
        "type": "conversation_part.list",
        "conversation_parts": [
            {
                "type": "conversation_part",
                "id": "6789",
                "part_type": "comment",
                "body": "<p>Good test</p>",
                "created_at": 1425586731,
                "author": {
                    "type": "user",
                    "id": "029384"
                }
            },
            {
                "type": "conversation_part",
                "id": "9384",
                "part_type": "close",
                "body": null,
                "created_at": 1425929944,
                "author": {
                    "type": "admin",
                    "id": "9382"
            }
        ]
    }
}

总是有一个initial_message,但是会话部分数组中可能有也可能没有任何内容,并且该数组可能有任意数量的成员。

我试图在csv中捕获一些这些信息,虽然我对@csv函数没有运气

我试过了:

jq '"\(.type), \(.id), \(.created_at), \(.initial_message.type), \(.initial_message.id), \(.initial_message.author.type), \(.conversation_parts.conversation_parts[].part), \(.conversation_parts.conversation_parts[].id), \(.conversation_parts.conversation_parts[].part_type), \(.conversation_parts.conversation_parts[].created_at), \(.conversation_parts.conversation_parts[].author.type)"' \

但是它给了我所有可能的数组内部组合(我从这个例子得到32行结果)。

我正在编辑我正在寻找的信息总量,但我的理想是显示

1234, 567, initial, admin
1234, 6789, comment, user
1234, 9384, close, admin

如果可以的话我会没事的

1234, 567, admin, 6789, comment, user
1234, 567, admin, 9384, close, admin

我不能拥有的是

1234, 567, admin, 6789, comment, user
1234, 567, admin, 9384, comment, admin
1234, 567, admin, 6789, close, user
1234, 567, admin, 9384, close, admin

这就是我现在要得到的

我知道在jq和foreach函数中有一个长度函数,但是后来我在管道中纠结了如何遍历对话部分的数组。 任何帮助将非常感激!

jq中,如果您有一个数组,例如

[1,2,3]

那么使用[]数组迭代的字符串插值对象构造过滤器将生成多个字符串或对象,例如

$ jq -Mnc '[1,2,3] | {x:.[]}'
{"x":1}
{"x":2}
{"x":3}

$ jq -Mnc '[1,2,3] | "x:\(.[])"'
"x:1"
"x:2"
"x:3"

如果存在多个[] ,则将产生组合的笛卡尔积。 例如

$ jq -Mnc '[1,2,3] | "x:\(.[]) x:\(.[])"'
"x:1 x:1"
"x:2 x:1"
"x:3 x:1"
"x:1 x:2"
"x:2 x:2"
"x:3 x:2"
"x:1 x:3"
"x:2 x:3"
"x:3 x:3"

如果这不是您想要的,避免它的一种简单方法是将[]移出插值,例如

$ jq -Mnc '[1,2,3] | .[] | "x:\(.) x:\(.)"'
"x:1 x:1"
"x:2 x:2"
"x:3 x:3"

同样,在使用嵌套结构时, 变量绑定通常很有用。 例如

$ jq -Mnc '{a:100, b:[1,2,3]} | .a as $a | .b[] | "a:\($a) b:\(.)"'
"a:100 b:1"
"a:100 b:2"
"a:100 b:3"

最后,这里有一个使用这些功能来解决这个问题的过滤器。 函数用于保持处理初始消息和会话部分的逻辑分离。

def initial:
    .id as $id
  | .initial_message
  |   .type as $ity
  |   .id   as $iid
  |   .author
  |     .type as $iaty
  |     "\($id), \($iid), \($ity), \($iaty)"
;

def parts:
    .id as $id
  | .conversation_parts.conversation_parts[]  # note [] here
  |   .id as $cid
  |   .part_type as $cpt
  |   .author
  |     .type as $caty
  |     "\($id), \($cid), \($cpt), \($caty)"
;

  initial
, parts

如果filter.jq包含此过滤器,而data.json包含样本数据,则

$ jq -M -r -f filter.jq data.json

会产生

1234, 567, initial_message, admin
1234, 6789, comment, user
1234, 9384, close, admin

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM