Representación de null en JSON


¿Cuál es el método preferido para devolver valores nulos en JSON? ¿Hay una preferencia diferente para los primitivos?

Por ejemplo, si mi objeto en el servidor tiene un Entero llamado "myCount" sin valor, el JSON más correcto para ese valor sería:

{}

O

{
    "myCount": null
}

O

{
    "myCount": 0
}

La misma pregunta para Cadenas - si tengo una cadena nula "myString" en el servidor, es el mejor JSON:

{}

O

{
    "myString": null
}

O

{
    "myStrung": ""
}

O (señor ayúdame)

{
    "myString": "null"
}

Me gusta la convención para que las colecciones se representen en el JSON como una colección vacía http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html

Se representaría un Array vacío:

{
    "myArray": []
}

EDITAR Resumen

El argumento de la 'preferencia personal' parece realista, pero corto en eso, ya que una comunidad consumirá un mayor número de servicios/fuentes dispares. Las convenciones para la estructura JSON ayudarían a normalizar el consumo y la reutilización de dichos servicios. En cuanto al establecimiento de un estándar, sugeriría adoptar la mayoría de las convenciones de Jackson con algunas excepciones:

  • Los objetos son preferibles a los primitivos.
  • Las colecciones vacías son preferidas a null.
  • Los objetos sin valor se representan como null.
  • Los primitivos devuelven su valor.

Si devuelve un objeto JSON con casi null valores, es posible que tenga un candidato para refactorizar en múltiples servicios.

{

    "value1": null,

    "value2": null,

    "text1": null,

    "text2": "hello",

    "intValue": 0, //use primitive only if you are absolutely sure the answer is 0

    "myList": [],

    "myEmptyList": null, //NOT BEST PRACTICE - return [] instead

    "boolean1": null, //use primitive only if you are absolutely sure the answer is true/false

    "littleboolean": false

}

El JSON anterior se generó a partir de la siguiente clase Java.

package jackson;

import java.util.ArrayList;
import java.util.List;

import com.fasterxml.jackson.databind.ObjectMapper;

public class JacksonApp {

    public static class Data {

        public Integer value1;

        public Integer value2;

        public String text1;

        public String text2 = "hello";

        public int intValue;

        public List<Object> myList = new ArrayList<Object>();

        public List<Object> myEmptyList;

        public Boolean boolean1;

        public boolean littleboolean;

    }

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        System.out.println(mapper.writeValueAsString(new Data()));
    }
}

Dependencia Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.3.0</version>
</dependency>
Author: austin, 2014-01-14

7 answers

Vamos a evaluar el análisis de cada uno:

Http://jsfiddle.net/brandonscript/Y2dGv /

var json1 = '{}';
var json2 = '{"myCount": null}';
var json3 = '{"myCount": 0}';
var json4 = '{"myString": ""}';
var json5 = '{"myString": "null"}';
var json6 = '{"myArray": []}';

console.log(JSON.parse(json1)); // {}
console.log(JSON.parse(json2)); // {myCount: null}
console.log(JSON.parse(json3)); // {myCount: 0}
console.log(JSON.parse(json4)); // {myString: ""}
console.log(JSON.parse(json5)); // {myString: "null"}
console.log(JSON.parse(json6)); // {myArray: []}

El tl; dr aquí:

JSON2 es la forma en que la especificación JSON indica que null debe estar representada. Pero como siempre, depende de lo que estés haciendo sometimes a veces la forma "correcta" de hacerlo no siempre funciona para tu situación. Usa tu juicio y toma una decisión informada.


JSON1 {}

Esto devuelve un objeto vacío. No hay datos allí, y solo te dirá que cualquier clave que estés buscando (ya sea myCount o algo más) es del tipo undefined.


JSON2 {"myCount": null}

En este caso, myCount está realmente definido, aunque su valor es null. Esto es no lo mismo que " no undefined y no null", y si estuviera probando una condición u otra, esto podría tener éxito mientras que JSON1 lo haría fallar.

Esta es la forma definitiva de representar null por la especificación JSON.


JSON3 {"myCount": 0}

En este caso, myCount es 0. Eso no es lo mismo que null, y no es lo mismo que false. Si su declaración condicional evalúa myCount > 0, entonces esto podría valer la pena. Además, si está ejecutando cálculos basados en el valor aquí, 0 podría ser útil. Sin embargo, si está tratando de probar null, esto en realidad no va a funcionar en todo.


JSON4 {"myString": ""}

En este caso, se obtiene una cadena vacía. De nuevo, como con JSON2, está definido, pero está vacío. Puedes probar if (obj.myString == "") pero no puedes probar null o undefined.


JSON5 {"myString": "null"}

Esto probablemente te va a meter en problemas, porque estás configurando el valor string a null; en este caso, obj.myString == "null" sin embargo, es no == null.


JSON6 {"myArray": []}

Esto te dirá que tu array myArray existe, pero está vacío. Esto es útil si está tratando de realizar un recuento o evaluación en myArray. Por ejemplo, supongamos que desea evaluar el número de fotos que un usuario publicó-podría hacer myArray.length y devolvería 0: definido, pero no se publicaron fotos.

 227
Author: brandonscript,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-28 23:15:14

null no es cero. No es un valor, per se: es un valor fuera del dominio de la variable que indica datos faltantes o desconocidos.

Solo hay una forma de representar null en JSON. Por las especificaciones (RFC 4627 y json.org):

2.1.  Values

A JSON value MUST be an object, array, number, or string, or one of
the following three literal names:

  false null true

introduzca la descripción de la imagen aquí

 170
Author: Nicholas Carey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-03-31 17:18:38

Solo hay una forma de representar null; es decir, con null.

console.log(null === null);   // true
console.log(null === true);   // false
console.log(null === false);  // false
console.log(null === 'null'); // false
console.log(null === "null"); // false
console.log(null === "");     // false
console.log(null === []);     // false
console.log(null === 0);      // false

Es decir, si alguno de los clientes que consumen su representación JSON utilizan el operador ===, podría ser un problema para ellos.

Sin valor

Si desea transmitir que tiene un objeto cuyo atributo myCount no tiene valor:

{ "myCount": null }

Sin atributo / atributo faltante

¿Qué pasa si usted transmite que usted tiene un objeto sin atributos:

{}

Cliente el código intentará acceder a myCount y obtener undefined; no está allí.

Colección vacía

¿Qué pasa si usted transmite que tiene un objeto con un atributo myCount que es una lista vacía:

{ "myCount": [] }
 15
Author: dnozay,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-12-18 17:35:35

Usaría null para mostrar que no hay valor para esa clave en particular. Por ejemplo, use null para indicar que se desconoce el "número de dispositivos de su hogar que se conectan a Internet".

Por otro lado, use {} si esa clave en particular no es aplicable. Por ejemplo, no debe mostrar un recuento, incluso si null, a la pregunta "número de automóviles que tiene conexión a Internet activa" se le pregunta a alguien que no posee ningún automóvil.

Evitaría incumplir cualquier valor a menos que ese defecto tenga sentido. Si bien puede decidir usar null para representar ningún valor, ciertamente nunca use "null" para hacerlo.

 12
Author: marcoseu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-15 15:29:46

Elegiría "default" para el tipo de variable de datos (null para cadenas/objetos, 0 para números), pero de hecho verifique qué código que consumirá el objeto espera. No olvide que a veces hay distinción entre null/default vs. "not present".

Echa un vistazo a null object pattern - a veces es mejor pasar algún objeto especial en lugar de null (es decir, [] array en lugar de null para matrices o "" para cadenas).

 6
Author: Alexei Levenkov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-14 18:28:50

Esta es una elección personal y situacional. Lo importante a recordar es que la cadena vacía y el número cero son conceptualmente distintos de null.

En el caso de un count probablemente siempre quieras algún número válido (a menos que el count sea desconocido o indefinido), pero en el caso de cadenas, ¿quién sabe? La cadena vacía podría significar algo en su aplicación. O tal vez no, eso depende de ti decidir.

 2
Author: Wayne Burkett,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-14 18:29:32

De acuerdo con la especificación JSON , el contenedor más externo no tiene que ser un diccionario (u 'objeto') como se implica en la mayoría de los comentarios anteriores. También puede ser una lista o un valor desnudo (es decir, string, number, boolean o null). Si desea representar un valor nulo en JSON, la cadena JSON completa (excluyendo las comillas que contienen la cadena JSON) es simplemente null. Sin llaves, sin corchetes, sin comillas. Puede especificar un diccionario que contenga una clave con un valor nulo ({"key1":null}), o una lista con un valor null ([null]), pero estos no son valores null en sí mismos - son diccionarios y listas propias. Del mismo modo, un diccionario vacío ({}) o una lista vacía ([]) están perfectamente bien, pero tampoco son nulos.

En Python:

>>> print json.loads('{"key1":null}')
{u'key1': None}
>>> print json.loads('[null]')
[None]
>>> print json.loads('[]')
[]
>>> print json.loads('{}')
{}
>>> print json.loads('null')
None
 0
Author: iggie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-10 20:31:40