Darstellung von null in JSON

421

Was ist die bevorzugte Methode zum Zurückgeben von Nullwerten in JSON? Gibt es eine andere Präferenz für Primitive?

Wenn mein Objekt auf dem Server beispielsweise eine Ganzzahl namens "myCount" ohne Wert hat, ist der korrekteste JSON für diesen Wert:

{}

oder

{
    "myCount": null
}

oder

{
    "myCount": 0
}

Gleiche Frage für Strings - Wenn ich einen Null-String "myString" auf dem Server habe, ist dies der beste JSON:

{}

oder

{
    "myString": null
}

oder

{
    "myString": ""
}

oder (Herr, hilf mir)

{
    "myString": "null"
}

Ich mag die Konvention, dass Sammlungen im JSON als leere Sammlung dargestellt werden http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html

Ein leeres Array würde dargestellt:

{
    "myArray": []
}

EDIT Zusammenfassung

Das Argument der „persönlichen Präferenz“ erscheint realistisch, ist jedoch insofern kurzsichtig, als wir als Gemeinschaft immer mehr unterschiedliche Dienste / Quellen konsumieren werden. Konventionen für die JSON-Struktur würden dazu beitragen, den Verbrauch und die Wiederverwendung dieser Dienste zu normalisieren. In Bezug auf die Festlegung eines Standards würde ich vorschlagen, die meisten Jackson-Konventionen mit wenigen Ausnahmen zu übernehmen:

  • Objekte werden gegenüber Grundelementen bevorzugt.
  • Leere Sammlungen werden Null vorgezogen.
  • Objekte ohne Wert werden als null dargestellt.
  • Primitive geben ihren Wert zurück.

Wenn Sie ein JSON-Objekt mit größtenteils Nullwerten zurückgeben, haben Sie möglicherweise einen Kandidaten für das Refactoring in mehrere 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

}

Der obige JSON wurde aus der folgenden Java-Klasse generiert.

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()));
    }
}

Maven-Abhängigkeit:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.3.0</version>
</dependency>
Pherris
quelle
5
Es gibt keinen besten Weg. Wählen Sie aus, was für den Kunden in Ihrem konkreten Anwendungsfall am einfachsten zu konsumieren ist. Überlegen Sie im Sinne der Rückgabe leerer Sammlungen null, ob Ihr Client mit der leeren Zeichenfolge besser zurechtkommt oder null- eine Zeichenfolge mit dem Wort "null" nicht von einem gültigen Wert zu unterscheiden ist. Tun Sie dies nicht.
Philipp Reichart
3
0 oder eine leere Zeichenfolge kann durchaus eine andere Bedeutung als null haben, die eine andere Bedeutung haben kann als das nicht vorhandene Attribut. Wenn Sie null darstellen möchten, verwenden Sie null. Es ist das expliziteste.
John Sheehan
In Objective-C gibt es eine definierte NSNullKlasse mit einer Singleton-Instanz. Ein Verweis auf diese Instanz entspricht JSONs null. Ich würde vermuten, dass eine andere Sprache das Gleiche tun könnte. Natürlich müsste man die Klasse des empfangenen Objekts überprüfen, bevor man sie in die vermutete Klasse umwandelt - sei sozusagen "nullbewusst".
Hot Licks
2
Beachten Sie, dass eine "Null" -Liste auch in Java nicht die beste Vorgehensweise ist: Wenn erwartet wird, dass die Liste leer ist, initialisieren Sie sie mit einer leeren Liste. Wenn es leer bleiben muss (z. B. weil es im Großhandel durch eine neue Liste ersetzt wird, anstatt zum Hinzufügen von Werten geändert zu werden), initialisieren Sie es in der leeren Liste (dh Collections.emptyList()). Auf diese Weise werden Null-Referenzfehler vermieden, die ansonsten schmerzhaft sein können.
Periata Breatta
@HotLicks - das ist nur möglich, weil Objective-C dynamisch eingegeben wird. In Java könnten Sie beispielsweise keine (nützliche) NullKlasse haben, da Sie ihre Werte nur Objekten ihres eigenen Typs oder Typs zuweisen könnten Object.
Periata Breatta

Antworten:

378

Lassen Sie uns die Analyse jedes einzelnen bewerten:

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: []}

Die tl; dr hier:

Das Fragment in dem json2 Variable ist die Art und Weise der JSON spec anzeigt nullsollte dargestellt werden. Aber wie immer hängt es davon ab, was Sie tun - manchmal funktioniert der "richtige" Weg nicht immer für Ihre Situation. Verwenden Sie Ihr Urteilsvermögen und treffen Sie eine fundierte Entscheidung.


JSON1 {}

Dies gibt ein leeres Objekt zurück. Es gibt dort keine Daten und es wird Ihnen nur sagen, dass jeder Schlüssel, den Sie suchen (sei es myCountoder etwas anderes), vom Typ ist undefined.


JSON2 {"myCount": null}

In diesem Fall myCountist tatsächlich definiert, obwohl sein Wert ist null. Dies ist nicht dasselbe wie "nicht undefinedund nicht null". Wenn Sie auf die eine oder andere Bedingung testen, ist dies möglicherweise erfolgreich, während JSON1 fehlschlagen würde.

Dies ist die endgültige Darstellung nullgemäß der JSON-Spezifikation .


JSON3 {"myCount": 0}

In diesem Fall ist myCount 0. Das ist nicht dasselbe wie nullund es ist nicht dasselbe wie false. Wenn Ihre bedingte Anweisung ausgewertet wird myCount > 0, ist dies möglicherweise sinnvoll. Wenn Sie hier Berechnungen basierend auf dem Wert ausführen, kann 0 hilfreich sein. Wenn Sie jedoch versuchen zu testen null, wird dies überhaupt nicht funktionieren.


JSON4 {"myString": ""}

In diesem Fall erhalten Sie eine leere Zeichenfolge. Wie bei JSON2 ist es wieder definiert, aber leer. Sie könnten testen für, if (obj.myString == "")aber Sie könnten nicht testen für nulloder undefined.


JSON5 {"myString": "null"}

Dies wird Sie wahrscheinlich in Schwierigkeiten bringen, da Sie den Zeichenfolgenwert auf null setzen. in diesem Fall ist obj.myString == "null"es jedoch nicht == null .


JSON6 {"myArray": []}

Dadurch erfahren Sie, dass Ihr Array myArrayvorhanden, aber leer ist. Dies ist nützlich, wenn Sie versuchen, eine Zählung oder Bewertung durchzuführen myArray. Angenommen, Sie myArray.lengthmöchten die Anzahl der von einem Benutzer geposteten Fotos bewerten. Dies ist möglich, und es wird Folgendes zurückgegeben 0: definiert, aber keine geposteten Fotos.

Brandonscript
quelle
1
Vielen Dank, sehr hilfreich. Nur ein kleiner Seitenknoten; Wenn Play Json (Scala) serialisiert Option [String] = Keine Ergebnis ist JSON1dh{}
Neil
207

nullist nicht Null. Es ist nicht ein Wert, per se : es ist ein Wert außerhalb des Bereichs der Variablen anzeigt , fehlt oder unbekannte Daten.

Es gibt nur eine Möglichkeit, nullin JSON darzustellen . Gemäß den Spezifikationen ( RFC 4627 und json.org ):

2.1. Werte

Ein JSON-Wert MUSS ein Objekt, ein Array, eine Zahl oder eine Zeichenfolge oder eines von sein
die folgenden drei wörtlichen Namen:

  false null true

Geben Sie hier die Bildbeschreibung ein

Nicholas Carey
quelle
8
Es ist so schade, dass null überhaupt vorhanden sein muss. 4 Zeichen für nichts. Es wäre schön gewesen, den Wert einfach ganz auszuschließen. json = '{"myValue":}';
Richard A Quadling
119
@Richard A Quadling - Ich bin ein Anhänger von Hal Abelsons "Programme müssen geschrieben werden, damit Menschen sie lesen können, und nur im Übrigen, damit Maschinen ausgeführt werden können". Ich würde das Wort "null" vorziehen, um die Absicht des Programmierers zu bestätigen, und nicht nur eine Frage des versehentlichen Auslassens.
Scott Smith
13
@ Dave May: "JSON-Werte sind keine Programme" - Bei meinem Punkt geht es darum, Absichten auf eindeutige Weise zu signalisieren. Ja, es kostet zusätzlich vier Zeichen, und für einige Anwendungen kann der Unterschied erheblich sein. In vielen Fällen ist jedoch die Vorteile der Herstellung Fehler falsch aussehen weit die Vorteile von kleineren Optimierungen überwiegt.
Scott Smith
11
@ Dave Laut json.org ist JSON "für Menschen leicht zu lesen und zu schreiben".
Sophivorus
14
Beachten Sie auch, dass JSON nicht der beste Ansatz ist, wenn Sie Probleme mit 4 ASCII-Zeichen haben. Sehen Sie sich Binary JSON oder besser ein reines Binärformat an.
PhoneixS
26

Es gibt nur einen Weg, um darzustellen null; das ist mit 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

Das heißt; Wenn einer der Clients, die Ihre JSON-Darstellung verwenden, den ===Operator verwendet. es könnte ein Problem für sie sein.

kein Wert

Wenn Sie vermitteln möchten, dass Sie ein Objekt haben, dessen Attribut myCountkeinen Wert hat:

{ "myCount": null }

kein Attribut / fehlendes Attribut

Was ist, wenn Sie vermitteln möchten, dass Sie ein Objekt ohne Attribute haben:

{}

Der Client-Code versucht zuzugreifen myCountund abzurufen undefined. es ist nicht da.

leere Sammlung

Was ist, wenn Sie vermitteln möchten, dass Sie ein Objekt mit einem Attribut haben myCount, das eine leere Liste ist:

{ "myCount": [] }
dnozay
quelle
+1 gute Beispiele mit Vergleichen, aber es wäre hilfreich, zwischen Javascript und Json zu unterscheiden, was bedeutet, dass die Darstellung von Null in Javascript nicht mit der von Json übereinstimmen musste (obwohl dies der Fall ist).
Mladen B.
15

Ich würde verwenden, um nullzu zeigen, dass es für diesen bestimmten Schlüssel keinen Wert gibt. Verwenden Sie zum Beispielnull darzustellen, dass "Anzahl der Geräte in Ihrem Haushalt, die eine Verbindung zum Internet herstellen" unbekannt ist.

Verwenden Sie andererseits, {}wenn dieser bestimmte Schlüssel nicht anwendbar ist. Zum Beispiel sollten Sie keine Zählung anzeigen, auch wennnull die Frage "Anzahl der Autos mit aktiver Internetverbindung" an jemanden gestellt wird, der keine Autos besitzt.

Ich würde es vermeiden, einen Wert als Standard festzulegen, es sei denn, dieser Standard ist sinnvoll. Während Sie sich möglicherweise dafür entscheiden, nullkeinen Wert darzustellen, verwenden Sie dies sicherlich niemals "null".

Marcoseu
quelle
7

Ich würde "Standard" für den Datentyp der Variablen auswählen ( nullfür Zeichenfolgen / Objekte, 0für Zahlen), aber tatsächlich prüfen, welchen Code das Objekt erwartet. Vergessen Sie nicht, dass es manchmal einen Unterschied zwischen null/ default und "nicht vorhanden" gibt.

Überprüfen Sie das Nullobjektmuster - manchmal ist es besser, ein spezielles Objekt anstelle von null(dh []Array anstelle von nullArrays oder ""Zeichenfolgen) zu übergeben.

Alexei Levenkov
quelle
2

Dies ist eine persönliche und situative Entscheidung. Wichtig ist, dass sich die leere Zeichenfolge und die Zahl Null konzeptionell von unterscheiden null.

Im Fall von a countmöchten Sie wahrscheinlich immer eine gültige Nummer (es sei denn, die countist unbekannt oder undefiniert), aber im Fall von Zeichenfolgen, wer weiß? Die leere Zeichenfolge könnte etwas in Ihrer Anwendung bedeuten . Oder vielleicht auch nicht. Die Entscheidung liegt bei Ihnen.

Wayne
quelle
1

Gemäß der JSON-Spezifikation muss der äußerste Container kein Wörterbuch (oder 'Objekt') sein, wie in den meisten obigen Kommentaren impliziert. Es kann auch eine Liste oder ein bloßer Wert sein (dh Zeichenfolge, Zahl, Boolescher Wert oder Null). Wenn Sie einen Nullwert in JSON darstellen möchten, ist die gesamte JSON-Zeichenfolge (mit Ausnahme der Anführungszeichen, die die JSON-Zeichenfolge enthalten) einfach null. Keine Klammern, keine Klammern, keine Anführungszeichen. Sie können ein Wörterbuch angeben, das einen Schlüssel mit einem Nullwert ( {"key1":null}) oder eine Liste mit einem Nullwert ( [null]) enthält. Dies sind jedoch selbst keine Nullwerte, sondern geeignete Wörterbücher und Listen. Ebenso sind ein leeres Wörterbuch ( {}) oder eine leere Liste ( []) vollkommen in Ordnung, aber auch nicht null.

In 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
iggie
quelle
Beachten Sie, dass die McKeeman Form-Grammatik in der rechten Seitenleiste der verknüpften JSON-Spezifikationsseite die Behauptung bestätigt, dass bare nulleinen gültigen JSON darstellt. Der Haupttext und die Abbildungen dort sind mehrdeutig und wenn irgendetwas darauf hindeutet, sind nur Objekte und Arrays an der Wurzel gültig.
yoyoyoyosef