Ich entwickle einen API-Client, in dem ich auf Anfrage eine JSON-Nutzlast codieren und einen JSON-Body aus der Antwort decodieren muss.
Ich habe den Quellcode aus mehreren Bibliotheken gelesen und nach dem, was ich gesehen habe, habe ich grundsätzlich zwei Möglichkeiten, eine JSON-Zeichenfolge zu codieren und zu decodieren.
Verwenden Sie die json.Unmarshal
Übergabe der gesamten Antwortzeichenfolge
data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
err = json.Unmarshal(data, value)
}
oder mit json.NewDecoder.Decode
err = json.NewDecoder(resp.Body).Decode(value)
In meinem Fall io.Reader
scheint die zweite Version beim Umgang mit implementierten HTTP-Antworten weniger Code zu erfordern, aber da ich beide gesehen habe, frage ich mich, ob es eine Präferenz gibt, ob ich eine Lösung anstelle der anderen verwenden soll.
Darüber hinaus lautet die akzeptierte Antwort auf diese Frage
Bitte verwenden Sie
json.Decoder
anstelle vonjson.Unmarshal
.
aber der Grund wurde nicht erwähnt. Sollte ich die Verwendung wirklich vermeiden json.Unmarshal
?
ioutil.ReadAll
ist fast immer das Falsche. Es hängt nicht mit Ihrem Ziel zusammen, erfordert jedoch, dass Sie über genügend zusammenhängenden Speicher verfügen, um alles zu speichern, was möglicherweise über die Pipe kommt, selbst wenn die letzten 20 TB der Antwort nach den letzten}
in Ihrem JSON liegen.io.LimitReader
, um dies zu verhindern.Antworten:
Es hängt wirklich davon ab, was Ihre Eingabe ist. Wenn Sie sich die Implementierung der
Decode
Methode von ansehenjson.Decoder
, wird der gesamte JSON-Wert im Speicher gepuffert, bevor die Zuordnung zu einem Go-Wert aufgehoben wird. In den meisten Fällen wird es also nicht speichereffizienter sein (obwohl sich dies in einer zukünftigen Version der Sprache leicht ändern könnte).Eine bessere Faustregel lautet also:
json.Decoder
Sie diese Option, wenn Ihre Daten aus einemio.Reader
Datenstrom stammen oder Sie mehrere Werte aus einem Datenstrom dekodieren müssen.json.Unmarshal
Sie diese Option, wenn Sie die JSON-Daten bereits im Speicher haben.Für den Fall des Lesens aus einer HTTP-Anfrage würde ich auswählen,
json.Decoder
da Sie offensichtlich aus einem Stream lesen.quelle
Buffered
Methode können Sie alle zusätzlichen Daten anzeigen, die nach dem Wert in den internen Puffer eingelesen wurden.