Curl z multilinią JSON

85

Rozważ poniższe polecenie curl, czy możliwe jest zezwolenie na nową linię w JSON (bez minify) i wykonanie bezpośrednio w 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"
    }
}'

Po uruchomieniu powyższego polecenia wydaje się, że wystąpił błąd w second { Jak naprawić powyższe polecenie?

Zaktualizowano : faktycznie udało mi się uruchomić polecenie bez problemu wcześniej, nie jestem pewien, dlaczego problem pojawił się ostatnio.

Ryan
źródło
1
Czy możesz nam powiedzieć więcej o błędzie? Twój przykład działa „tak jak jest” w moim systemie. mymac > bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15) Copyright (C) 2007 Free Software Foundation, Inc.
Eric Bolinger
Tak, dla mnie też działa:GNU bash, version 4.3.42(1)-release
miken32
1
Sprawdź również składnię napisów w stylu ANSI C :echo $'here is a newline:\nand here is a tab:\t'
miken32
application/jsonjest prawidłowym typem nośnika dla danych JSON - zobacz RFC4627
Pockets i

Odpowiedzi:

124

Przypomniałem sobie inny sposób zrobienia tego z "Here Document", jak opisano na stronie podręcznika Bash i wyszczególniono tutaj . Te @-środki do zapoznania się z korpusu ze standardowego wejścia, a << EOFśrodkiem do rury treść skryptu aż „EOF” jako standardowego wejścia zwijają. Ten układ może być łatwiejszy do odczytania niż używanie oddzielnych plików lub podejście „echo a variable”.

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

UWAGA: Użyj --trace <outfile>opcji zwijania, aby dokładnie zarejestrować , co przechodzi przez drut. Z jakiegoś powodu, podejście Here Document usuwa znaki nowej linii. (Aktualizacja: znaki nowej linii zostały usunięte przez opcję curl -d. Poprawione!)

Eric Bolinger
źródło
5
To jest czyste, bez dodatkowego cytowania, bez ucieczki i działa bardzo dobrze. Dzięki.
Seth
Czy możemy używać potoków o takiej składni?
Ivan Balashov
2
Tak, możesz przesłać dane wyjściowe do innego polecenia, chociaż umieszczenie jest dokładnie pośrodku. Dodaj przekierowanie stdout po przekierowaniu stdin. Przykład użycia liczby słów:-d @- << EOF | wc
Eric Bolinger
2
To nie tutaj Dokument usuwa nowe linie, ale curl -dopcja: curl.haxx.se/docs/manpage.html#-d . Służy --data-binarydo zachowania znaków nowej linii i powrotu karetki.
dzieciou
39

Zgodnie z sugestią Martina dotyczącą umieszczenia JSON w zmiennej, możesz również umieścić JSON w oddzielnym pliku, a następnie podać nazwę pliku, -dużywając składni @ 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

Wada jest oczywista (2 lub więcej plików tam, gdzie byłeś). Ale z drugiej strony, twój skrypt może zaakceptować nazwę pliku lub argument katalogu i nigdy nie będziesz musiał go edytować, po prostu uruchom go na różnych plikach JSON. To, czy jest to przydatne, zależy od tego, co próbujesz osiągnąć.

Bampfer
źródło
1
Uwaga: upewnij się, że zawartość json jest prawidłowa na stronie jsonlint.com
vikramvi,
To podejście jest przejrzyste i łatwe do debugowania w porównaniu do innych.
vikramvi,
Świetne rozwiązanie. Uważaj jednak na PATH!
Pierre Ferry
21

Z jakiegoś powodu, podejście Here Document usuwa znaki nowej linii

@ eric-bolinger powodem, dla którego Heredoc usuwa nowe linie, jest to, że musisz powiedzieć swojemu Heredocowi, aby zachował nowe linie, cytując 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

Zwróć uwagę na pojedyncze tiki otaczające EOF przy pierwszym zdefiniowaniu, ale nie za drugim.

Tim Gebhardt
źródło
20

Powinieneś użyć zewnętrznych podwójnych cudzysłowów i uciec przed wszystkimi wewnętrznymi cudzysłowami w ten sposób:

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\"
    }
}"
Dmitriy Korobkov
źródło
19

Możesz przypisać swój json do zmiennej:

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

Teraz możesz przekazać to do zwijania za pomocą 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 @-
Martin Konecny
źródło
Używanie pojedynczych cudzysłowów do otaczania bloku oznacza, że ​​nie możesz używać zmiennych (np. ${username}) W JSON.
Air
Tak, ale używanie podwójnych cudzysłowów oznacza, że ​​nie możesz używać znaków $ w swoich danych. Wybierz, który z nich jest odpowiedni dla Ciebie.
Martin Konecny