Quelle est la méthode recommandée pour renvoyer des valeurs NULL en JSON? Existe-t-il une préférence différente pour les primitives?
Par exemple, si mon objet sur le serveur a un Integer appelé "myCount" sans valeur, le JSON le plus correct pour cette valeur serait:
{}
ou
{
"myCount": null
}
ou
{
"myCount": 0
}
Même question pour Strings - si j'ai une chaîne vide "myString" sur le serveur, le meilleur JSON:
{}
ou
{
"myString": null
}
ou
{
"myString": ""
}
ou (Seigneur aide-moi)
{
"myString": "null"
}
J'aime la convention selon laquelle les collections sont représentées dans le JSON sous la forme d'une collection vide http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html
Un tableau vide serait représenté:
{
"myArray": []
}
EDIT Résumé
L'argument des "préférences personnelles" semble réaliste, mais à courte vue, en tant que communauté, nous consommerons un nombre toujours croissant de services/sources disparates. Les conventions relatives à la structure JSON permettraient de normaliser la consommation et la réutilisation desdits services. En ce qui concerne l'établissement d'une norme, je suggérerais d'adopter la plupart des conventions de Jackson à quelques exceptions près:
Si vous renvoyez un objet JSON avec des valeurs généralement nulles, 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>
É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:
Le fragment de la variable json2 est le moyen la spécification JSON indique que
null
devrait ê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 dans votre situation. Utilisez votre jugement et prenez une décision éclairée.
JSON1 {}
Cela retourne un objet vide. Il n'y a pas de données là-bas, et cela va seulement vous dire que la clé que vous cherchez (que ce soit myCount
ou quelque chose d'autre) est de type undefined
.
JSON2 {"myCount": null}
Dans ce cas, myCount
est défini, bien que sa valeur soit null
. Ceci est pas la même chose que "pas undefined
et pas null
", et si vous testiez une condition ou l'autre, cela pourrait réussir alors que JSON1 échouerait.
C'est la manière définitive de représenter null
par la spécification JSON .
JSON3 {"myCount": 0}
Dans ce cas, myCount vaut 0. Ce n'est pas la même chose que null
et ce n'est pas la même chose que false
. Si votre instruction conditionnelle évalue myCount > 0
, alors cela peut être intéressant. De plus, si vous exécutez des calculs basés sur la valeur indiquée, 0 peut être utile. Si vous essayez de tester null
, cela ne fonctionnera pas du tout.
JSON4 {"myString": ""}
Dans ce cas, vous obtenez une chaîne vide. Encore une fois, comme pour JSON2, c'est défini, mais c'est vide. Vous pouvez tester if (obj.myString == "")
mais vous ne pouvez pas tester null
ni undefined
.
JSON5 {"myString": "null"}
Cela vous causera probablement des problèmes, car vous définissez la valeur string sur null; dans ce cas, obj.myString == "null"
mais c'est pas == null
.
JSON6 {"myArray": []}
Cela vous dira que votre tableau myArray
existe, mais qu'il est vide. Ceci est utile si vous essayez d'effectuer un compte ou une évaluation sur myArray
. Par exemple, supposons que vous vouliez évaluer le nombre de photos postées par un utilisateur. Vous pouvez faire myArray.length
et renvoyer 0
: défini, mais aucune photo.
null
n'est pas zéro. Ce n'est pas une valeur, en soi : c'est une valeur en dehors du domaine de la variable indiquant des données manquantes ou inconnues.
Il n'y a qu'un seul moyen de représenter null
en JSON. Selon les spécifications ( RFC 4627 et json.org ):
2.1. Valeurs Une valeur JSON DOIT être un objet, un tableau, un nombre ou une chaîne, ou l'un des Des trois noms littéraux suivants: . false null true
Il n'y a qu'un seul moyen de représenter null
; c'est-à-dire 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 utilisent votre représentation JSON, utilisez l'opérateur ===
. cela pourrait être un problème pour eux.
Si vous voulez indiquer que vous avez un objet dont l'attribut myCount
n'a pas de valeur:
{ "myCount": null }
Et si vous transmettez que vous avez un objet sans attribut:
{}
Le code client essaiera d'accéder à myCount
et d'obtenir undefined
; Ce n'est pas là.
Que se passe-t-il si vous indiquez 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 indiquer que "le nombre de périphériques de votre ménage qui se connecte à Internet" est inconnu.
D'autre part, utilisez {}
si cette clé n'est pas applicable. Par exemple, vous ne devez pas afficher de compte, même si null
, à la question "Nombre de voitures disposant d'une connexion Internet active" est demandé à une personne ne possédant aucune voiture.
J'éviterais de remplacer une valeur par défaut, à moins que cette valeur par défaut ait du sens. Bien que vous puissiez décider d'utiliser null
pour ne représenter aucune valeur, n'utilisez jamais "null"
pour le faire.
Je choisirais "par défaut" pour le type de données de la variable (null
pour les chaînes/objets, 0
pour les nombres), mais vérifierais effectivement quel code sera consommé par l'objet. N'oubliez pas qu'il y a parfois une distinction entre null
/default et "non présent".
Check out modèle d'objet null - Parfois, il est préférable de passer un objet spécial au lieu de null
(c'est-à-dire []
array au lieu de null
pour les 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 count
est inconnu ou indéfini), mais dans le cas des chaînes, qui sait? La chaîne vide pourrait moyenne quelque chose dans votre application. Ou peut-être que non. C'est à vous de décider.
Selon la spécification JSON , le conteneur le plus externe ne doit pas obligatoirement être un dictionnaire (ou un "objet"), comme l'implique la plupart des commentaires ci-dessus. Il peut aussi s'agir d'une liste ou d'une valeur nue (chaîne, nombre, booléen ou null). Si vous souhaitez représenter une valeur NULL en JSON, l'intégralité de la chaîne JSON (à l'exception des guillemets contenant la chaîne JSON) est simplement null
. Pas d'accolades, pas de crochets, pas de guillemets. Vous pouvez spécifier un dictionnaire contenant une clé avec une valeur nulle ({"key1":null}
) ou une liste avec une valeur nulle ([null]
), mais ce ne sont pas des valeurs nulles elles-mêmes - ce sont des dictionnaires et des listes corrects. De même, un dictionnaire vide ({}
) ou une liste vide ([]
) conviennent parfaitement, 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