Завиток с многострочным JSON

85

Рассмотрим команду curl ниже, можно ли разрешить новую строку в JSON (без minify) и выполнить непосредственно в 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 { Как исправить указанную выше команду?

Обновлено : на самом деле я смог запустить команду без проблем ранее, не знаю, почему проблема возникла недавно.

Райан
источник
1
Вы можете подробнее рассказать об ошибке? Ваш пример работает в моей системе "как есть". 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
miken32
1
Также ознакомьтесь с синтаксисом строк вecho $'here is a newline:\nand here is a tab:\t'
стиле
application/jsonправильный тип носителя для данных JSON - см. RFC4627
Pocketsand

Ответы:

124

Я вспомнил другой способ сделать это с помощью «Здесь документа», как описано на странице руководства Bash и подробно описано здесь . В @-средстве для чтения тела из 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 <outfile>curl, чтобы точно записать , что проходит по проволоке. По какой-то причине этот подход Here Document удаляет новые строки. (Обновление: новые строки были удалены с помощью опции curl -d. Исправлено!)

Эрик Болинджер
источник
5
Это чисто, без лишних цитирований, без экранирования и работает очень хорошо. Благодарю.
Сет,
Можно ли использовать каналы с таким синтаксисом?
Иван Балашов
2
Да, вы можете передать вывод другой команде, хотя размещение находится прямо посередине. Добавьте перенаправление stdout после перенаправления stdin. Пример использования подсчета слов:-d @- << EOF | wc
Эрик Болинджер
2
Новые строки удаляются не здесь, а в документе curl -d: curl.haxx.se/docs/manpage.html#-d . Используется --data-binaryдля сохранения символов новой строки и возврата каретки.
dzieciou
39

Наряду с предложением Мартина поместить JSON в переменную, вы также можете поместить JSON в отдельный файл, а затем указать имя файла, -dиспользуя синтаксис @ curl:

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. Насколько это полезно, зависит от того, чего вы пытаетесь достичь.

Бампфер
источник
1
Примечание: убедитесь, что у вас есть действительный json-контент через jsonlint.com
vikramvi
Этот подход понятен и прост в отладке по сравнению с другими.
vikramvi
Отличное решение. Будьте осторожны с PATH!
Pierre Ferry,
21

По какой-то причине этот подход Here Document удаляет новые строки

@ eric-bolinger причина, по которой Heredoc удаляет символы новой строки, заключается в том, что вам нужно указать своему Heredoc сохранять символы новой строки, цитируя EOF:

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 в первый раз, когда он определяется, но не во второй.

Тим Гебхардт
источник
20

Вы должны использовать внешние двойные кавычки и избегать всех внутренних кавычек следующим образом:

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\"
    }
}"
Дмитрий Коробков
источник
19

Вы можете присвоить свой json переменной var:

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

Теперь вы можете переслать это в curl, используя stdin:

echo $json | curl -0 -v -X POST http://www.example.com/api/users \
-H "Expect:" \
-H 'Content-Type: text/json; charset=utf-8' \
-d @-
Мартин Конечны
источник
Использование одинарных кавычек для окружения блока означает, что вы не можете использовать переменные (например ${username}) в JSON.
Air
Да, но использование двойных кавычек означает, что вы не можете использовать знаки $ в своих данных. Выберите подходящий именно вам.
Мартин Конечны