Représentation de null dans JSON
Quelle est la méthode préférée pour renvoyer des valeurs null dans JSON? Y a-t-il une préférence différente pour les primitives?
Par exemple, si mon objet sur le serveur a un entier appelé "myCount" sans valeur, le JSON le plus correct pour cette valeur serait:
{}
Ou
{
"myCount": null
}
Ou
{
"myCount": 0
}
Même question pour les chaînes-si j'ai une chaîne nulle "myString" sur le serveur, est le meilleur JSON:
{}
Ou
{
"myString": null
}
Ou
{
"myStrung": ""
}
Ou (seigneur aide-moi)
{
"myString": "null"
}
J'aime que la convention pour les collections soit représentée dans le JSON comme une collection vide http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html
Un tableau vide serait représenté:
{
"myArray": []
}
Modifier le résumé
L'argument de la "préférence personnelle" semble réaliste, mais court en ce sens qu'une communauté consommera un plus grand nombre de services/sources disparates. Les Conventions pour la structure JSON aideraient à normaliser la consommation et la réutilisation desdits services. En ce qui concerne l'établissement d'une norme, je suggère d'adopter la plupart des conventions de Jackson à quelques exceptions près:
- les objets sont préférés aux primitives.
- les collections vides sont préférées à null.
- les objets sans valeur sont représentés par null.
- les Primitives renvoient leur valeur.
Si vous renvoyez un objet JSON avec principalement null valeurs, vous pouvez avoir un candidat pour le refactoring dans plusieurs services.
{
"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
}
Le JSON ci-dessus a été généré à partir de la classe Java suivante.
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()));
}
}
Dépendance Maven:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.3.0</version>
</dependency>
7 réponses
Évaluons l'analyse de chacun:
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: []}
Le tl;dr ici:
JSON2 {[42] } est la façon dont la spécification JSON indique que
null
doit être représenté. Mais comme toujours, cela dépend de ce que vous faites-parfois la "bonne" façon de le faire ne fonctionne pas toujours pour votre situation. Faites preuve de jugement et prenez une décision éclairée.
JSON1 {}
Renvoie un objet vide. Il n'y a pas de données là-bas, et cela va seulement vous dire que quelle que soit la clé que vous cherchez (que ce soit myCount
ou autre chose) est de type undefined
.
JSON2 {"myCount": null}
Dans ce cas, myCount
est réellement défini, bien que sa valeur soit null
. C'est pas la même chose que les deux " pas undefined
et pas null
", et si vous testiez une condition ou l'autre, cela pourrait réussir alors que JSON1 le ferait échouer.
C'est la façon définitive de représenter null
par la spécification JSON.
JSON3 {"myCount": 0}
Dans ce cas, myCount vaut 0. Ce n'est pas le même que null
, et ce n'est pas le même que false
. Si votre instruction conditionnelle évalue myCount > 0
, cela pourrait en valoir la peine. De plus, si vous exécutez des calculs basés sur la valeur ici, 0 pourrait être utile. Si vous essayez de tester pour null
cependant, cela ne va pas fonctionner à tout.
JSON4 {"myString": ""}
Dans ce cas, vous obtenez une chaîne vide. Encore une fois, comme avec JSON2, il est défini, mais il est vide. Vous pouvez le tester pour if (obj.myString == "")
, mais vous ne pourrais pas tester pour null
ou undefined
.
JSON5 {"myString": "null"}
Cela va probablement vous causer des problèmes, car vous définissez la valeurstring sur null; dans ce cas, obj.myString == "null"
mais ce n'est pas == null
.
JSON6 {"myArray": []}
Cela vous dira que votre tableau myArray
existe, mais il est vide. Ceci est utile si vous essayez d'effectuer un comptage ou une évaluation sur myArray
. Par exemple, disons que vous vouliez évaluer le nombre de photos publiées par un utilisateur - vous pourriez faire myArray.length
et il retournerait 0
: défini, mais aucune photo postée.
null
n'est pas nul. Ce n'est pas une valeur, soi: c'est une valeur en dehors du domaine de la variable indiquant manquantes ou inconnues de données.
Il N'y a qu'une seule façon de représenter null
dans JSON. Par les spécifications (RFC 4627 et 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
Il n'y a qu'une façon de représenter null
, c'est avec 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
C'est-à-dire, si l'un des clients qui consomment votre représentation JSON d'utiliser le ===
opérateur; il pourrait être un problème pour eux.
Aucune valeur
Si vous voulez transmettre que vous avez un objet dont les attributs myCount
n'a pas de valeur:
{ "myCount": null }
Aucun attribut / attribut manquant
Que faire si vous transmettez que vous avez un objet sans attributs:
{}
Client le code va essayer d'accéder à myCount
et obtenir undefined
; ce n'est pas là.
Collection vide
Que faire si vous transmettez que vous avez un objet avec un attribut myCount
qui est une liste vide:
{ "myCount": [] }
J'utiliserais null
pour montrer qu'il n'y a pas de valeur pour cette clé particulière. Par exemple, utilisez null
pour représenter que "le nombre d'appareils dans votre ménage se connecte à internet" est inconnu.
D'autre part, utiliser {}
si cette clé n'est pas applicable. Par exemple, vous ne devriez pas montrer un compte, même si null
, à la question "nombre de voitures qui ont une connexion Internet active" est demandé à quelqu'un qui ne possède pas de voitures.
J'éviterais toute valeur par défaut sauf si cette valeur par défaut est logique. Bien que vous puissiez décider d'utiliser null
pour ne représenter aucune valeur, n'utilisez certainement jamais "null"
pour le faire.
Je choisirais "default" pour le type de variable de données (null
pour les chaînes / objets, 0
pour les nombres), mais en effet vérifier quel code qui va consommer l'objet attend. N'oubliez pas qu'il y a parfois une distinction entre null
/ default et "non présent".
Découvrez objet null modèle - parfois, il vaut mieux passer à quelque objet spécial au lieu de null
(c - []
tableau au lieu de null
pour tableaux ou ""
pour les chaînes).
C'est un choix personnel et situationnel. La chose importante à retenir est que la chaîne vide et le nombre zéro sont conceptuellement distincts de null
.
Dans le cas d'un count
vous voulez probablement toujours un nombre valide (sauf si le {[1] } est inconnu ou indéfini), mais dans le cas des chaînes, qui sait? La chaîne vide pourrait signifier quelque chose dans votre application. Ou peut-être qu'il ne l'est pas. C'est à vous de décider.
Selon la spécification JSON , le conteneur le plus externe ne doit pas nécessairement être un dictionnaire (ou un 'objet') comme indiqué dans la plupart des commentaires ci-dessus. Il peut également s'agir d'une liste ou d'une valeur nue (c'est-à-dire chaîne, Nombre, booléen ou null). Si vous voulez représenter une valeur null dans JSON, la chaîne JSON entière (à l'exclusion des guillemets contenant la chaîne JSON) est simplement null
. Pas d'accolades, pas de parenthèses, pas de guillemets. Vous pouvez spécifier un dictionnaire contenant une clé avec une valeur null ({"key1":null}
), ou une liste avec les une valeur nulle ([null]
), mais ce ne sont pas des valeurs nulles elles-mêmes - ce sont des dictionnaires et des listes appropriés. De même, un dictionnaire vide ({}
) ou une liste vide ([]
) sont parfaitement corrects, mais ne sont pas non plus nuls.
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