Curl mit mehrzeiliger JSON

83

Betrachten Sie den folgenden Curl-Befehl. Ist es möglich, Newline in JSON (ohne Minify) zuzulassen und direkt in Bash (Mac / Ubuntu) auszuführen?

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"
    }
}'

Wenn ich den obigen Befehl ausführe, scheint ein Fehler beim second { Beheben des obigen Befehls aufgetreten zu sein .

Aktualisiert : Eigentlich konnte ich den Befehl zuvor ohne Probleme ausführen, nicht sicher, warum das Problem kürzlich aufgetreten ist.

Ryan
quelle
1
Können Sie uns mehr über den Fehler erzählen? Ihr Beispiel funktioniert auf meinem System "wie es ist". mymac > bash --version GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin15) Copyright (C) 2007 Free Software Foundation, Inc.
Eric Bolinger
Ja, funktioniert auch für mich:GNU bash, version 4.3.42(1)-release
miken32
1
echo $'here is a newline:\nand here is a tab:\t'
Schauen
application/jsonist der richtige Medientyp für JSON-Daten - siehe RFC4627
Pocketsand

Antworten:

119

Ich erinnerte mich an eine andere Möglichkeit, dies mit einem "Hier-Dokument" zu tun, wie in der Bash-Manpage beschrieben und hier detailliert beschrieben . Das @-bedeutet, den Body aus STDIN zu lesen, während der Skriptinhalt << EOFbis "EOF" als STDIN zum Einrollen weitergeleitet wird. Dieses Layout ist möglicherweise einfacher zu lesen als die Verwendung separater Dateien oder der Ansatz "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

HINWEIS: Verwenden Sie die --trace <outfile>Curl-Option, um genau aufzuzeichnen , was über den Draht geht. Aus irgendeinem Grund werden bei diesem Here Document-Ansatz Zeilenumbrüche entfernt. (Update: Zeilenumbrüche wurden mit der Option curl -d entfernt. Korrigiert!)

Eric Bolinger
quelle
5
Dies ist sauber, kein zusätzliches Zitieren, kein Entkommen und es funktioniert sehr gut. Vielen Dank.
Seth
Können wir Pipes mit einer solchen Syntax verwenden?
Ivan Balashov
2
Ja, Sie können die Ausgabe an einen anderen Befehl weiterleiten, obwohl die Platzierung genau in der Mitte liegt. Fügen Sie die Standardumleitung nach der Standardumleitung hinzu. Beispiel mit Wortzahl:-d @- << EOF | wc
Eric Bolinger
2
Es ist nicht Here Document, das neue Zeilen entfernt, sondern curl -dOption: curl.haxx.se/docs/manpage.html#-d . Verwenden Sie --data-binarydiese Option, um Zeilenumbruch- und Wagenrücklaufzeichen beizubehalten.
dzieciou
35

In Anlehnung an Martins Vorschlag, den JSON in eine Variable einzufügen, können Sie den JSON auch in eine separate Datei einfügen und dann den Dateinamen für die -dVerwendung der @ -Syntax von curl angeben:

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

Der Nachteil liegt auf der Hand (2 oder mehr Dateien, in denen Sie früher eine hatten). Auf der positiven Seite könnte Ihr Skript jedoch einen Dateinamen oder ein Verzeichnisargument akzeptieren, und Sie müssten es nie bearbeiten, sondern nur auf verschiedenen JSON-Dateien ausführen. Ob dies nützlich ist, hängt davon ab, was Sie erreichen möchten.

Bampfer
quelle
1
Hinweis: Stellen
Vikramvi
Dieser Ansatz ist sauber und im Vergleich zu anderen einfach zu debuggen.
Vikramvi
Tolle Lösung. Pass auf PATH tho auf!
Pierre Ferry
20

Sie sollten äußere doppelte Anführungszeichen verwenden und alle inneren Anführungszeichen wie folgt maskieren:

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
quelle
19

Sie können Ihren JSON einer Variablen zuweisen:

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

Jetzt können Sie dies an Curl weiterleiten, indem Sie 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
quelle
Wenn Sie den Block in einfache Anführungszeichen setzen, können Sie ${username}im JSON keine Variablen (z. B. ) verwenden.
Air
Ja, aber wenn Sie doppelte Anführungszeichen verwenden, können Sie in Ihren Daten keine $ -Zeichen verwenden. Wählen Sie aus, welches für Sie das richtige ist.
Martin Konecny
19

Aus irgendeinem Grund werden bei diesem Here Document-Ansatz Zeilenumbrüche entfernt

@ eric-bolinger Der Grund, warum der Heredoc Zeilenumbrüche entfernt, ist, dass Sie Ihrem Heredoc mitteilen müssen, dass er Zeilenumbrüche beibehalten soll, indem Sie den EOF zitieren:

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

Beachten Sie die einzelnen Häkchen, die EOF beim ersten Definieren umgeben, aber nicht beim zweiten.

Tim Gebhardt
quelle