【问题标题】:Curl with multiline of JSON多行 JSON 卷曲
【发布时间】:2016-04-23 05:25:11
【问题描述】:

考虑下面的 curl 命令,是否可以在 JSON 中允许换行符(没有缩小)并直接在 bash 中执行(Mac/Ubuntu)

curl -0 -v -X POST http://www.example.com/api/users \
-H "Expect:" \
-H 'Content-Type: text/json; charset=utf-8' \
-d \
'
{
    "field1": "test",
    "field2": {
        "foo": "bar"
    }
}'

当我运行上面的命令时,second { 似乎发生了错误 如何修复上述命令?

更新:实际上我之前能够运行该命令而没有问题,不知道为什么最近会出现问题。

【问题讨论】:

  • 你能告诉我们更多关于错误的信息吗?您的示例在我的系统上“按原样”运行。 mymac > bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15) Copyright (C) 2007 Free Software Foundation, Inc.
  • 是的,也适用于我:GNU bash, version 4.3.42(1)-release
  • 也可以查看ANSI C-like string syntaxecho $'here is a newline:\nand here is a tab:\t'
  • application/json 是 JSON 数据的正确媒体类型 -- 请参阅 RFC4627

标签: bash shell ubuntu curl


【解决方案1】:

我认为这可以是一个答案

curl -0 -v -X POST http://www.example.com/api/users \
-H "Expect:" \
-H 'Content-Type: text/json; charset=utf-8' \
--data-raw '
{
    "field1": "test",
    "field2": {
        "foo": "bar"
    }
}'

【讨论】:

    【解决方案2】:

    我记得 Bash 手册页和 detailed here 中描述的另一种使用“此处文档”的方法。 @- 表示从 STDIN 读取正文,而 << EOF 表示将脚本内容通过管道传输到“EOF”作为 STDIN 卷曲。这种布局可能比使用单独的文件或“回显变量”方法更易于阅读。

    curl -0 -v -X POST http://www.example.com/api/users \
    -H "Expect:" \
    -H 'Content-Type: application/json; charset=utf-8' \
    --data-binary @- << EOF
    {
        "field1": "test",
        "field2": {
            "foo": "bar"
        }
    }
    EOF
    

    注意:使用--trace &lt;outfile&gt; curl 选项准确地记录通过网络传输的内容。出于某种原因,这种 Here Document 方法去除了换行符。 (更新:curl -d 选项去除了换行符。已更正!)

    【讨论】:

    • 这很干净,没有额外的引用,没有转义,而且效果很好。谢谢。
    • 我们可以使用这种语法的管道吗?
    • 是的,您可以将输出通过管道传输到另一个命令,尽管位置就在中间。在标准输入重定向之后添加标准输出重定向。使用字数统计的示例:-d @- &lt;&lt; EOF | wc
    • 去除新行的不是 Here Document,而是 curl -d 选项:curl.haxx.se/docs/manpage.html#-d。使用--data-binary 保留换行符和回车符。
    • 可以在 JSON 中插入变量吗?我不这么认为。
    【解决方案3】:

    由于某种原因,这种 Here Document 方法去除了换行符

    @eric-bolinger Heredoc 去除换行符的原因是因为您需要通过引用 EOF 来告诉 Heredoc 保留换行符:

    curl -0 -v -X POST http://www.example.com/api/users \
    -H "Expect:" \
    -H 'Content-Type: text/json; charset=utf-8' \
    -d @- <<'EOF'
    
    {
        "field1": "test",
        "field2": {
            "foo": "bar"
        }
    }
    EOF
    

    请注意第一次定义 EOF 时围绕它的单个刻度,但不是第二次。

    【讨论】:

      【解决方案4】:

      按照 Martin 将 JSON 放入变量中的建议,您也可以将 JSON 放入单独的文件中,然后使用 curl 的 @ 语法将文件名提供给 -d

      curl -0 -v -X POST http://www.example.com/api/users \
        -H "Expect:" \
        -H 'Content-Type: text/json; charset=utf-8' \
        -d @myfile.json
      

      缺点很明显(以前有 2 个或多个文件。)但从好的方面来说,你的脚本可以接受文件名或目录参数,你永远不需要编辑它,只需在不同的地方运行它JSON 文件。这是否有用取决于您要完成的工作。

      【讨论】:

      • 注意:确保您通过jsonlint.com获得有效的json内容
      • 与其他方法相比,这种方法干净且易于调试。
      • 很好的解决方案。小心 PATH !
      【解决方案5】:

      您可以将您的 json 分配给一个 var:

      json='
      {
          "field1": "test",
          "field2": {
              "foo": "bar"
          }
      }'
      

      现在您可以使用 stdin 将其转发给 curl:

      echo $json | curl -0 -v -X POST http://www.example.com/api/users \
      -H "Expect:" \
      -H 'Content-Type: text/json; charset=utf-8' \
      -d @-
      

      【讨论】:

      • 使用单引号将块括起来意味着您不能在 JSON 中使用变量(例如 ${username})。
      • 是的,但是使用双引号意味着您不能在数据中使用 $ 符号。选择适合您的。
      【解决方案6】:

      您应该使用外部双引号,并转义所有内部引号,如下所示:

      curl -0 -v -X POST http://www.example.com/api/users \
      -H "Expect:" \
      -H 'Content-Type: text/json; charset=utf-8' \
      -d \
      "
      {
          \"field1\": \"test\",
          \"field2\": {
              \"foo\": \"bar\"
          }
      }"
      

      【讨论】:

        猜你喜欢
        • 2016-08-12
        • 2011-05-15
        • 2015-03-25
        • 1970-01-01
        • 1970-01-01
        • 2017-04-09
        • 1970-01-01
        • 2015-09-09
        • 2012-08-13
        相关资源
        最近更新 更多