È valido definire funzioni nei risultati JSON?


98

Parte della risposta JSON di un sito web aveva questo (... aggiunto per contesto):

{..., now:function(){return(new Date).getTime()}, ...}

L'aggiunta di funzioni anonime a JSON è valida? Mi aspetto che ogni volta che accedi a "time" restituisca un valore diverso.


Il JSON è stato analizzato correttamente dal browser? Se è così, allora sì, è valido (sotto questo aspetto).
harschware

7
@harschware - questo è vero solo perché JSON si riferisce a javascript. In quanto formato di serializzazione dei dati indipendente dalla lingua, è falso ed è una strada problematica da percorrere.
jsoverson

@jsoverson - Sono d'accordo. Vedi la mia risposta di seguito.
harschware

1
Facile rispondere a questa domanda te stesso: aperta kit su web inspector ed eseguire: JSON.parse('{now:function(){return(new Date).getTime()}'). L'ispettore dice: Uncaught SyntaxError: Unexpected token nuna rapida occhiata alle specifiche JSON lo conferma. Concentrati sulla sezione "valore".
Mark E. Haase

Risposte:


103

No.

JSON è puramente pensato per essere un linguaggio di descrizione dei dati. Come indicato su http://www.json.org , si tratta di un "formato di scambio di dati leggero". - non un linguaggio di programmazione.

Secondo http://en.wikipedia.org/wiki/JSON , i "tipi di base" supportati sono:

  • Numero (intero, reale o virgola mobile)
  • Stringa (Unicode tra virgolette doppie con escape della barra rovesciata)
  • Booleano (vero e falso)
  • Array (una sequenza ordinata di valori, separati da virgole e racchiusi tra parentesi quadre)
  • Oggetto (raccolta di chiavi: coppie di valori, separate da virgole e racchiuse tra parentesi graffe)
  • null

2
@Dr. Zim, no e per confrontare le cose con null quello che faccio è questo a==null?1:a.toString()==""Quello che fa è che se a = null allora restituisce 1 / true, se "" significa stringa vuota ottieni anche 1 / true .. se lo è non null o "", quindi restituirà 0 / false, puoi replicarlo di più per lavorare con [] e {} semplicemente aggiungerlo ?1:a==[]?1:a.toString()=={}.toString();al mio frammento precedente. quindi forse questa funzione ti aiuterà. isnull=(function(a){return (a==null?1:a.toString()==""?1:a==[]?1:a.toString()=={}.toString())?true:false})Vorrei usare ?1:0al posto di ?true:falsema (vero / falso)
JamesM-SiteGen

10
Allo stesso tempo, anche le funzioni sono dati.
argyle

2
Sono atterrato qui mentre cercavo un modo per recuperare "ulteriori dati" utilizzando JSON. Sarebbe bello informare un client (dal server) come ottenere ulteriori dati, senza che il client si preoccupi di quale REST o più api chiamare successivamente.
Ravindranath Akila

3
@RavindranathAkila REST implica che le possibili successive chiamate API siano esposte nella chiamata. In altre parole: la richiesta REST che hai fatto, ti dice quali richieste future potresti voler fare (in base alla logica decisionale dell'applicazione e ai dati). Un perfetto esempio di ciò è l'API Github, in cui vengono restituiti elementi di dati, ma alcuni di essi portano ad altre risorse di richiesta API.
Jens A. Koch

1
@ Grazie Jens-AndréKoch! Sarà il check-out
Ravindranath Akila

16

Il problema è che JSON come linguaggio di definizione dei dati si è evoluto da JSON come notazione dell'oggetto JavaScript. Poiché Javascript supporta eval su JSON, è legittimo inserire codice JSON all'interno di JSON (in quel caso d'uso). Se stai usando JSON per passare i dati da remoto, direi che è una cattiva pratica inserire metodi in JSON perché potresti non aver modellato bene la tua interazione client-server. Inoltre, quando si desidera utilizzare JSON come linguaggio di descrizione dei dati, direi che potresti metterti nei guai incorporando metodi perché alcuni parser JSON sono stati scritti con in mente solo la descrizione dei dati e potrebbero non supportare le definizioni dei metodi nella struttura.

La voce JSON di Wikipedia è un buon argomento per non includere metodi in JSON, citando problemi di sicurezza:

A meno che non ti fidi assolutamente della fonte del testo e hai la necessità di analizzare e accettare il testo che non è strettamente conforme a JSON, dovresti evitare eval () e utilizzare JSON.parse () o un altro parser specifico JSON. Un parser JSON riconoscerà solo il testo JSON e rifiuterà altro testo, che potrebbe contenere JavaScript malevolo. Nei browser che forniscono supporto JSON nativo, i parser JSON sono anche molto più veloci di eval. Si prevede che il supporto JSON nativo sarà incluso nel prossimo standard ECMAScript.


2
Potresti usare il termine JSON in modo colloquiale, ma ufficialmente "JSON" è uno standard ECMA che non mette a nudo gli oggetti funzione da codificare. Non dovrebbero esserci ambiguità sulle capacità a cui ti riferisci quando dici "JSON": questo è il punto centrale dell'avere uno standard.
Mark E. Haase

D'accordo che è vero oggi. Non ho una fonte da citare, ma credo che JSON fosse un termine coniato prima che ECMA entrasse nel gioco Javascript, e prima che JSON fosse un formato di scambio dati standard ... quindi ho usato il termine 'evoluto'
harschware

@harschware Secondo RFC 4627, JSON è stato creato da ECMA.
Jenna Sloan

9

Citiamo una delle specifiche: http://tools.ietf.org/html/rfc7159#section-12

La specifica del formato di interscambio dei dati JSON (The JavaScript Object Notation) afferma:

JSON è un sottoinsieme di JavaScript ma esclude assegnazioni e invocazioni.

Poiché la sintassi di JSON è presa in prestito da JavaScript, è possibile utilizzare la funzione "eval ()" di quel linguaggio per analizzare i testi JSON. Ciò costituisce generalmente un rischio per la sicurezza inaccettabile, poiché il testo
potrebbe contenere codice eseguibile insieme a dichiarazioni di dati
. La stessa considerazione si applica all'uso di funzioni simili a eval () in qualsiasi altro linguaggio di programmazione in cui i testi JSON sono conformi alla
sintassi di quel linguaggio.

Quindi tutte le risposte che affermano che le funzioni non fanno parte dello standard JSON sono corrette.

La risposta ufficiale è: No, non è valido definire funzioni nei risultati JSON!


La risposta potrebbe essere sì, perché "il codice è dato" e "il dato è codice". Anche se JSON viene utilizzato come formato di serializzazione dei dati indipendente dal linguaggio, funzionerà un tunneling di "codice" attraverso altri tipi.

Una stringa JSON potrebbe essere utilizzata per passare una funzione JS al browser lato client per l'esecuzione.

[{"data":[["1","2"],["3","4"]],"aFunction":"function(){return \"foo bar\";}"}]

Questo porta a domande del tipo: come " eseguire il codice JavaScript memorizzato come una stringa ".

Siate pronti ad alzare il flag "eval () is evil" e attaccare il flag "non eseguire il tunnel delle funzioni tramite JSON" accanto ad esso.



4

No, assolutamente no.

Se utilizzi un serializzatore JSON decente, non ti consentirà di serializzare una funzione del genere. È un OBJECT valido, ma non un JSON valido. Qualunque sia l'intento di quel sito Web, non sta inviando JSON valido.


2
Uso JSON-Lib e lo considero un ottimo serializzatore. Dalla [pagina di utilizzo] (json-lib.sourceforge.net/usage.html) puoi vedere che serializzerà perfettamente le funzioni
harschware

Interessante ... non l'ho mai visto prima. Non è assolutamente da specificare ( json.org afferma esplicitamente che JSON è indipendente dal linguaggio, che le definizioni di funzione non lo sono), ma comunque interessante.
jvenema

È divertente che dovrebbe essere indipendente dalla lingua, ma JSON sta per JavaScript Object Notation hmm weird ..
Nate-Wilkins

3

JSON esclude esplicitamente le funzioni perché non è concepito per essere una struttura dati solo JavaScript (nonostante il JS nel nome).


3

Una risposta breve è NO ...

JSON è un formato di testo completamente indipendente dal linguaggio, ma utilizza convenzioni familiari ai programmatori della famiglia di linguaggi C, inclusi C, C ++, C #, Java, JavaScript, Perl, Python e molti altri. Queste proprietà rendono JSON un linguaggio ideale per lo scambio di dati.

Guarda il motivo per cui:

Quando si scambiano dati tra un browser e un server, i dati possono essere solo testo.

JSON è testo e possiamo convertire qualsiasi oggetto JavaScript in JSON e inviare JSON al server.

Possiamo anche convertire qualsiasi JSON ricevuto dal server in oggetti JavaScript.

In questo modo possiamo lavorare con i dati come oggetti JavaScript, senza analisi e traduzioni complicate.

Ma aspetta ...

Esistono ancora modi per memorizzare la tua funzione, è ampiamente sconsigliato , ma è comunque possibile:

Abbiamo detto, puoi salvare un string... che ne dici di convertire la tua funzione in una stringa, allora?

const data = {func: '()=>"a FUNC"'};

Quindi puoi stringere i dati usando JSON.stringify(data)e poi usando JSON.parseper analizzarli (se questo passaggio è necessario) ...

E eval per eseguire una funzione stringa (prima di farlo, ti basta sapere che l'uso di eval è ampiamente sconsigliato):

eval(data.func)(); //return "a FUNC"

0

Tramite l'utilizzo di NodeJS (sintassi commonJS) sono stato in grado di far funzionare questo tipo di funzionalità, inizialmente avevo solo una struttura JSON all'interno di un file JS esterno, ma volevo che quella struttura fosse più di una classe, con metodi che potevano essere decisi a tempo di esecuzione.

La dichiarazione di "Executor" in myJSON non è richiesta.

var myJSON = {
    "Hello": "World",
    "Executor": ""
}

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}

-3

Le espressioni di funzione in JSON sono completamente possibili, ma non dimenticare di racchiuderle tra virgolette doppie. Ecco un esempio tratto dalla progettazione di database noSQL:

{
  "_id": "_design/testdb",
  "views": {
    "byName": {
      "map": "function(doc){if(doc.name){emit(doc.name,doc.code)}}"
    }
  }
}


La domanda riguarda una funzione, non una stringa. JSON supporta i valori di stringa, ma non supporta le funzioni. Vedi la risposta di Mike per i dettagli
jannis

@jann è possibile però. se aggiungi una funzione di auto invocazione come. le persone qui apparentemente non conoscono la risposta.
Roj

-4

sebbene eval non sia raccomandato, funziona:

<!DOCTYPE html>
<html>
<body>

<h2>Convert a string written in JSON format, into a JavaScript function.</h2>

<p id="demo"></p>

<script>
    function test(val){return val + " it's OK;}
    var someVar = "yup";
    var myObj = { "func": "test(someVar);" };
    document.getElementById("demo").innerHTML = eval(myObj.func);
</script>

</body>
</html>

1
votato perché non è necessario utilizzare HTML nell'esempio, questo è uno stile di codifica vecchio di 5 anni, manca una citazione e, i file JSON non dovrebbero contenere funzioni, se lo fanno non possono essere serializzati o archiviati in a no sql DB,
Martijn Scheffer

-5

Lascia fuori le virgolette ...

var a = {"b":function(){alert('hello world');} };

a.b();

Questo è JavaScript, la domanda si pone su JSON.
Quentin
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.