Estoy desarrollando una API de cliente donde tengo que codificar un JSON de carga en la solicitud y decodificar un JSON cuerpo de la respuesta.

He leído el código fuente de varias bibliotecas y de lo que he visto, tengo básicamente dos posibilidades para la codificación y decodificación de una cadena JSON.

Uso json.Deserializar pasar toda la cadena de respuesta de

data, err := ioutil.ReadAll(resp.Body)
if err == nil && data != nil {
    err = json.Unmarshal(data, value)
}

o el uso de json.NewDecoder.Decode

err = json.NewDecoder(resp.Body).Decode(value)

En mi caso, cuando se trata de las respuestas HTTP que implementa io.Reader, la segunda versión parece ser requiere menos código, pero desde que he visto, tanto que me pregunto si hay alguna preferencia si debo utilizar una solución en vez de la otra.

Por otra parte, el aceptó la respuesta de esta pregunta dice

Por favor utilice json.Decoder en lugar de json.Unmarshal.

pero no mencionó la razón. Debo realmente evitar el uso de json.Unmarshal?

  • Este tire de la solicitud en GitHub sustituye una llamada a Deserializar con json.NewDecoder para «quitar de búfer en la decodificación JSON.»
  • Sólo depende de lo que de entrada es más conveniente para usted. blog.golang.org/json-and-go da ejemplos de la utilización de ambas técnicas.
  • De la OMI, ioutil.ReadAll es casi siempre la cosa incorrecta a hacer. No relacionadas con tu objetivo, pero requiere que usted tenga suficiente memoria contigua para almacenar todo lo que podría venir abajo de la tubería, incluso si los últimos 20 TB de respuesta después de la última } en su JSON.
  • Usted puede utilizar io.LimitReader para evitar que.

1 Comentario

  1. 190

    Realmente depende de lo que tu entrada. Si usted mira en la aplicación de la Decode método de json.Decoder, neutraliza todo el JSON valor en la memoria antes de unmarshalling en un Ir de valor. Así, en la mayoría de los casos no va a ser más eficiente de la memoria (aunque esto podría cambiar en un futuro la versión de la lengua).

    Por lo que la mejor regla de oro es esta:

    • Uso json.Decoder si los datos provienen de una io.Reader corriente, o que usted necesita para decodificar varios valores de una secuencia de datos.
    • Uso json.Unmarshal si usted ya tiene los datos JSON en la memoria.

    Para el caso de la lectura de una solicitud HTTP, me quedaría con json.Decoder ya que estamos, evidentemente, la lectura de un arroyo.

    • También: mediante la inspección de la Ir 1.3 código fuente, también podemos aprender que para la codificación, si utiliza un json.Encoder, para la reutilización de un global de grupo de búfer (respaldado por la nueva sincronización.La piscina), que debe disminuir búfer de churn mucho si eres de codificación de un montón de json. Sólo hay un grupo global de manera diferente json.Encoder y compartirlo. La razón por la que esto no podía hacerse para el json.La jefa de la interfaz es debido a que los bytes se devuelve al usuario y el usuario no tiene una forma de «devolver» los bytes a la piscina. Así que si usted está haciendo un montón de codificación, json.La jefa siempre tiene un poco de amortiguamiento del churn.
    • estás seguro? El código fuente todavía dice que lee todo el valor en el buffer antes de decodificación: github.com/golang/go/blob/master/src/encoding/json/…. El Buffered método está allí para ayudarte a ver cualquier extra de datos que se leyó en el buffer interno, después del valor.
    • No, usted está probablemente en lo cierto. Yo era sólo la interpretación de su declaración de manera diferente de lo que quería. Disculpas por la confusión.

Dejar respuesta

Please enter your comment!
Please enter your name here