【问题标题】:jq - converting json to cvs - how to treat "null" as string?jq - 将 json 转换为 csv - 如何将“null”视为字符串?
【发布时间】:2021-09-03 14:45:01
【问题描述】:

我有以下想要转换为 csv 的 json 文件:

{
  "id": 1,
  "date": "2014-05-05T19:07:48.577"
}
{
  "id": 2,
  "date": null
}

使用以下 jq 将其转换为 csv 生成:

$ jq -sr '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.])) as $rows | $cols, $rows[] | @csv' < test.json
"date","id"
"2014-05-05T19:07:48.577",1
,2

不幸的是,对于“id”等于“2”的行,日期列未设置为“null” - 相反,它是空的。如果它是一个日期时间列,这反过来会导致 MySQL 在导入时出错(如果我们没有日期,它需要一个文字“null”,并且在“”上出错)。

如何让 jq 打印文字“null”,而不是“”?

【问题讨论】:

  • 我在-s 选项中进行了编辑,以便问题、示例输入和输出都保持一致。如果这不是本意,请随时重新编辑。

标签: json csv null export-to-csv jq


【解决方案1】:

我会选择:

(map(keys_unsorted) | add | unique) as $cols
| $cols,
  (.[] | [.[$cols[]]] | map(. // "null") )
| @csv

首先,使用keys_unsorted 可以避免无用的排序。

其次,[.[$cols[]]] 是一个重要的、反复出现的、惯用的模式,用于确保以正确的顺序构造数组,而无需借助 reduce 大锤。

第三,虽然map(. // "null")在这里似乎很合适,但需要注意的是,这个表达式也会将false替换为"null",所以,一般来说它是不合适的。相反,为了保留false,可以写成map(if . == null then "null" else . end)

第四,应该注意的是,如上所述使用map(. // "null") 也会掩盖任何键的缺失值,所以如果想要一些其他行为(例如,如果id 缺失,则会引发错误),然后替代方法是必要的。


以上假设问题中显示的 JSON 对象流是“slurped”,例如使用 jq 的 -s 命令行选项。

【讨论】:

  • 这个成语是我还没有遇到过的——很好! @Tomasz - 如果您希望值 false 转换为“null”,请使用 // "null" 如上所述;如果您希望false 转换为“false”,则将// "null" 替换为| tostring(尽管这也会对数字进行字符串化)。
【解决方案2】:

使用// 作为单元格值的替代运算符:

jq -r '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.] // "null")) as $rows | $cols, $rows[] | @csv' &lt; test.json

(整个字符串在这里解释得很好:https://stackoverflow.com/a/32965227/16174836

【讨论】:

    【解决方案3】:

    您可以通过将map($row[.]) 更改为map($row[.]|tostring) 来使用tostring 将值“字符串化”:

    $ cat so2332.json
    {
      "id": 1,
      "date": "2014-05-05T19:07:48.577"
    }
    {
      "id": 2,
      "date": null
    }
    
    $ jq --slurp --raw-output '(map(keys) | add | unique) as $cols | map(. as $row | $cols | map($row[.]|tostring)) as $rows | $cols, $rows[] | @csv' so2332.json
    "date","id"
    "2014-05-05T19:07:48.577","1"
    "null","2"
    

    请注意,使用tostring 会导致数字转换为字符串。

    【讨论】:

    • 从示例中可以明显看出,对所有键使用 tostring 会导致 id 变为 CSV 字符串,这可能是不可取的。
    • 确实——我在对您的回答的评论中提到了这一点,但在这里没有提到。我会添加一个注释。
    猜你喜欢
    • 2019-11-21
    • 2016-03-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-07
    • 1970-01-01
    • 1970-01-01
    • 2022-01-01
    相关资源
    最近更新 更多