Rappresenta null in JSON


423

Qual è il metodo preferito per restituire valori null in JSON? Esiste una preferenza diversa per i primitivi?

Ad esempio, se il mio oggetto sul server ha un numero intero chiamato "myCount" senza valore, il JSON più corretto per quel valore sarebbe:

{}

o

{
    "myCount": null
}

o

{
    "myCount": 0
}

Stessa domanda per le stringhe - se ho una stringa null "myString" sul server, è il JSON migliore:

{}

o

{
    "myString": null
}

o

{
    "myString": ""
}

o (signore aiutami)

{
    "myString": "null"
}

Mi piace che la convenzione per le raccolte sia rappresentata nel JSON come raccolta vuota http://jtechies.blogspot.nl/2012/07/item-43-return-empty-arrays-or.html

Un array vuoto sarebbe rappresentato:

{
    "myArray": []
}

Riepilogo EDIT

L'argomento delle "preferenze personali" sembra realistico, ma poco lungimirante in quanto, come comunità, consumeremo un numero sempre maggiore di servizi / fonti disparate. Le convenzioni per la struttura JSON aiuterebbero a normalizzare il consumo e il riutilizzo di tali servizi. Per quanto riguarda la definizione di uno standard, suggerirei di adottare la maggior parte delle convenzioni di Jackson con alcune eccezioni:

  • Gli oggetti sono preferiti rispetto alle primitive.
  • Le raccolte vuote sono preferite rispetto a null.
  • Gli oggetti senza valore sono rappresentati come null.
  • I primitivi restituiscono il loro valore.

Se si restituisce un oggetto JSON con valori prevalentemente nulli, è possibile che si abbia un candidato per il refactoring in più servizi.

{

    "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

}

Il JSON sopra è stato generato dalla seguente classe 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()));
    }
}

Dipendenza da Maven:

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.3.0</version>
</dependency>

5
Non esiste un modo migliore. Scegli ciò che è più semplice da consumare per il cliente nel tuo caso d'uso concreto. Nello spirito di restituire raccolte vuote invece di null, considera se il tuo client è meglio con la stringa vuota o null- una stringa contenente la parola "null" è indistinguibile da un valore valido, non farlo.
Philipp Reichart,

3
0 o una stringa vuota potrebbe benissimo avere un significato diverso da null, che potrebbe avere un significato diverso dall'attributo inesistente. Se si desidera rappresentare null, utilizzare null. È il più esplicito.
John Sheehan,

In Objective-C esiste una NSNullclasse definita che ha un'istanza singleton. Un riferimento a tale istanza equivale a JSON null. Immagino che un'altra lingua possa fare la stessa cosa. Ovviamente, si dovrebbe controllare la classe dell'oggetto ricevuto prima di lanciarla nella classe presunta - essere "nullo", per così dire.
Hot Licks

2
Notare che avere un elenco "null" non è neanche la migliore prassi in Java: se si prevede che l'elenco sia vuoto, inizializzarlo in un elenco vuoto. Se è necessario che rimanga vuoto (ad es. Perché verrà sostituito all'ingrosso da un nuovo elenco anziché modificato per aggiungere valori), inizializzarlo in un elenco vuoto (ad es Collections.emptyList().). In questo modo si evitano bug di riferimento null che potrebbero essere altrimenti un dolore.
Periata Breatta,

@HotLicks - questo è possibile solo perché Objective-C è digitato in modo dinamico. In Java, ad esempio, non potresti avere una Nullclasse (utile) perché potresti assegnare i suoi valori solo a oggetti del suo tipo o tipo Object.
Periata Breatta,

Risposte:


379

Valutiamo l'analisi di ciascuno:

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

Il tl; dr qui:

Il frammento nella variabile json2 è il modo in cui le specifiche JSON indicano che nulldovrebbero essere rappresentate. Ma come sempre, dipende da cosa stai facendo - a volte il modo "giusto" di farlo non sempre funziona per la tua situazione. Usa il tuo giudizio e prendi una decisione informata.


JSON1 {}

Questo restituisce un oggetto vuoto. Non ci sono dati lì, e ti dirà solo che qualunque chiave tu stia cercando (che sia myCounto qualcos'altro) è di tipo undefined.


JSON2 {"myCount": null}

In questo caso, in myCountrealtà è definito, anche se il suo valore è null. Questo non è lo stesso di entrambi "no undefinede non null" e se si eseguisse il test per una condizione o per l'altra, ciò potrebbe avere esito positivo mentre JSON1 fallirebbe.

Questo è il modo definitivo di rappresentare nullsecondo le specifiche JSON .


JSON3 {"myCount": 0}

In questo caso, myCount è 0. Non è lo stesso di null, e non è lo stesso di false. Se la tua dichiarazione condizionale viene valutata myCount > 0, potrebbe essere utile farlo. Inoltre, se stai eseguendo calcoli basati sul valore qui, 0 potrebbe essere utile. Se stai provando a provare nullcomunque, questo in realtà non funzionerà affatto.


JSON4 {"myString": ""}

In questo caso, ricevi una stringa vuota. Ancora una volta, come con JSON2, è definito, ma è vuoto. Potresti provare per if (obj.myString == "")ma non puoi testare per nullo undefined.


JSON5 {"myString": "null"}

Questo probabilmente ti metterà nei guai, perché stai impostando il valore della stringa su null; in questo caso, obj.myString == "null"tuttavia è non == null .


JSON6 {"myArray": []}

Questo ti dirà che il tuo array myArrayesiste, ma è vuoto. Questo è utile se stai cercando di eseguire un conteggio o una valutazione myArray. Ad esempio, supponiamo che tu voglia valutare il numero di foto pubblicate da un utente - potresti farlo myArray.lengthe tornerebbe 0: definito, ma nessuna foto pubblicata.


1
Grazie mille, molto utile. Solo un piccolo nodo laterale; quando Play Json (scala) serializza l'opzione [String] = Nessuno il risultato è JSON1ie{}
Neil

207

nullnon è zero. Di per sé non è un valore: è un valore esterno al dominio della variabile che indica i dati mancanti o sconosciuti.

C'è solo un modo per rappresentare nullin JSON. Secondo le specifiche ( RFC 4627 e json.org ):

2.1. Valori

Un valore JSON DEVE essere un oggetto, un array, un numero o una stringa o uno di
i seguenti tre nomi letterali:

  false null true

inserisci qui la descrizione dell'immagine


8
È un vero peccato che nulla debba essere presente. 4 personaggi per niente. Sarebbe stato bello semplicemente escludere del tutto il valore. json = '{"myValue":}';
Richard A Quadling,

119
@Richard A Quadling - Sono un seguace dei programmi di Hal Abelson "I programmi devono essere scritti per essere letti dalle persone, e solo per inciso per l'esecuzione delle macchine". Preferirei la parola "null", a conferma dell'intenzione del programmatore, e non solo una questione di omissione accidentale.
Scott Smith,

13
@Dave May: "I valori JSON non sono programmi" - Il mio punto è di segnalare l'intento in modo inequivocabile. Sì, costa altri quattro caratteri e per alcune applicazioni la differenza può essere significativa. In molti casi, tuttavia, i vantaggi della visualizzazione degli errori sono di gran lunga superiori ai vantaggi delle ottimizzazioni minori.
Scott Smith,

11
@Dave Inoltre, secondo json.org, JSON "è facile per gli umani leggere e scrivere".
Sophivorus,

14
Inoltre, se hai problemi con 4 caratteri ASCII, JSON non è l'approccio migliore, guarda Binary JSON o meglio in un formato binario puro.
PhoneixS,

26

C'è solo un modo per rappresentare null; quello è 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

Vale a dire; se uno dei client che consumano la tua rappresentazione JSON utilizza l' ===operatore; potrebbe essere un problema per loro.

nessun valore

Se vuoi comunicare di avere un oggetto il cui attributo myCountnon ha valore:

{ "myCount": null }

nessun attributo / attributo mancante

Cosa succede se si comunica che si dispone di un oggetto senza attributi:

{}

Il codice client tenterà di accedere myCounte ottenere undefined; Non è lì.

raccolta vuota

Che cosa succede se si comunica che si dispone di un oggetto con un attributo myCountche è un elenco vuoto:

{ "myCount": [] }

+1 buoni esempi con confronti, ma sarebbe utile distinguere tra javascript e json, il che significa che la rappresentazione di null in javascript non deve corrispondere a quella di json (anche se lo fa).
Mladen B.

15

Vorrei nullmostrare che non esiste alcun valore per quella chiave particolare. Ad esempio, utilizzare nullper indicare che "il numero di dispositivi in ​​casa si connette a Internet" è sconosciuto.

D'altra parte, utilizzare {}se quella particolare chiave non è applicabile. Ad esempio, non si dovrebbe mostrare un conteggio, anche se null, alla domanda "numero di auto con connessione Internet attiva" viene posta a qualcuno che non possiede alcuna macchina.

Eviterei di default qualsiasi valore a meno che quel default non abbia senso. Sebbene tu possa decidere di utilizzare nullper non rappresentare alcun valore, certamente non utilizzarlo mai "null"per farlo.


7

Sceglierei "default" per il tipo di dati della variabile ( nullper stringhe / oggetti, 0per i numeri), ma in effetti verificherei quale codice consumerà l'oggetto. Non dimenticare che a volte esiste una distinzione tra null/ default e "non presente".

Scopri il modello di oggetti null - a volte è meglio passare qualche oggetto speciale invece di null(cioè []array invece che nullper array o ""per stringhe).


2

Questa è una scelta personale e situazionale. La cosa importante da ricordare è che la stringa vuota e il numero zero sono concettualmente distinti danull .

Nel caso di a countprobabilmente vuoi sempre un numero valido (a meno che non countsia sconosciuto o indefinito), ma nel caso di stringhe, chi lo sa? La stringa vuota potrebbe significare qualcosa nella tua applicazione. O forse no. Sta a te decidere.


1

Secondo le specifiche JSON , il contenitore più esterno non deve essere un dizionario (o 'oggetto') come implicito nella maggior parte dei commenti sopra. Può anche essere un elenco o un valore non elaborato (ovvero stringa, numero, valore booleano o null). Se si desidera rappresentare un valore null in JSON, l'intera stringa JSON (escluse le virgolette contenenti la stringa JSON) è semplicemente null. Senza parentesi graffe, senza parentesi, senza virgolette. È possibile specificare un dizionario contenente una chiave con un valore null ( {"key1":null}) o un elenco con un valore null ( [null]), ma questi non sono valori null stessi - sono dizionari ed elenchi appropriati. Allo stesso modo, un dizionario vuoto ( {}) o un elenco vuoto ( []) vanno benissimo, ma non sono nulli.

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

Si noti che è la grammatica del modulo McKeeman sulla barra laterale destra della pagina delle specifiche JSON collegata che convalida l'asserzione che bare nullcostituisce JSON valido. Il testo e le illustrazioni del corpo principale sono ambigui e se qualcosa sembra suggerire che alla radice siano validi solo oggetti e matrici.
yoyoyoyosef,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.