Ist es gültig, Funktionen in JSON-Ergebnissen zu definieren?

98

Ein Teil der JSON-Antwort einer Website hatte Folgendes (... für den Kontext hinzugefügt):

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

Ist das Hinzufügen anonymer Funktionen zu JSON gültig? Ich würde erwarten, dass jedes Mal, wenn Sie auf 'time' zugreifen, ein anderer Wert zurückgegeben wird.

Zachary Scott
quelle
Hat der JSON vom Browser erfolgreich analysiert? Wenn ja, dann ist es ja gültig (in dieser Hinsicht).
Harschware
7
@harschware - das gilt nur, wenn JSON sich auf Javascript bezieht. Als sprachunabhängiges Daten-Serialisierungsformat ist es falsch und ein problematischer Weg.
Jsoverson
@jsoverson - ich stimme zu. Siehe meine Antwort unten.
Harschware
1
Diese Frage können Sie ganz einfach selbst beantworten: Öffnen Sie den Web-Kit-Inspektor und führen Sie Folgendes aus : JSON.parse('{now:function(){return(new Date).getTime()}'). Der Inspektor sagt: Uncaught SyntaxError: Unexpected token nEin kurzer Blick auf die JSON-Spezifikation bestätigt dies. Konzentrieren Sie sich auf den Abschnitt 'Wert'.
Mark E. Haase

Antworten:

103

Nein.

JSON ist lediglich als Datenbeschreibungssprache gedacht. Wie auf http://www.json.org erwähnt , handelt es sich um ein "leichtes Datenaustauschformat". - keine Programmiersprache.

Laut http://en.wikipedia.org/wiki/JSON werden folgende "Grundtypen" unterstützt:

  • Zahl (Ganzzahl, Real oder Gleitkomma)
  • String (Unicode in doppelten Anführungszeichen mit Escape-Schrägstrich)
  • Boolescher Wert (wahr und falsch)
  • Array (eine geordnete Folge von Werten, durch Kommas getrennt und in eckigen Klammern eingeschlossen)
  • Objekt (Sammlung von Schlüssel: Wertepaaren, durch Kommas getrennt und in geschweiften Klammern eingeschlossen)
  • null
Mike
quelle
2
@DR. Zim, nein und um die Dinge mit null zu vergleichen, was ich tue, ist dies. a==null?1:a.toString()==""Dies bedeutet, dass wenn a = null ist, 1 / true zurückgegeben wird. Wenn es "" bedeutet, was eine leere Zeichenfolge bedeutet, erhalten Sie auch 1 / true. Wenn dies der Fall ist nicht null oder "", dann wird 0 / false zurückgegeben. Sie können dies weiter replizieren, um mit [] zu arbeiten, und {} einfach ?1:a==[]?1:a.toString()=={}.toString();zu meinem vorherigen Snippet hinzufügen . Vielleicht hilft Ihnen diese Funktion. isnull=(function(a){return (a==null?1:a.toString()==""?1:a==[]?1:a.toString()=={}.toString())?true:false})Ich würde ?1:0anstelle von ?true:falseaber (wahr / falsch)
JamesM-SiteGen
10
Gleichzeitig sind Funktionen auch Daten.
Argyle
2
Ich bin hier gelandet, als ich einen Weg gefunden habe, mit JSON "weitere Daten" abzurufen. Es wäre schön, einen Client (vom Server) darüber zu informieren, wie er weitere Daten erhält, ohne dass sich der Client Gedanken darüber macht, welche REST- oder API-API als Nächstes aufgerufen werden soll.
Ravindranath Akila
3
@ RavindranathAkila REST impliziert, dass mögliche nächste API-Aufrufe im Aufruf verfügbar gemacht werden. Mit anderen Worten: Die von Ihnen durchgeführte REST-Anforderung gibt an, welche zukünftigen Anforderungen Sie möglicherweise ausführen möchten (basierend auf der Anwendungsentscheidungslogik und den Daten). Ein perfektes Beispiel hierfür ist die Github-API, bei der Datenelemente zurückgegeben werden. Einige davon führen jedoch zu anderen API-Anforderungsressourcen.
Jens A. Koch
1
@ Jens-AndréKoch Danke! Werde es überprüfen
Ravindranath Akila
16

Das Problem ist, dass JSON als Datendefinitionssprache aus JSON als JavaScript-Objektnotation hervorgegangen ist. Da Javascript die Auswertung von JSON unterstützt, ist es legitim, JSON-Code in JSON einzufügen (in diesem Anwendungsfall). Wenn Sie JSON verwenden, um Daten remote zu übergeben, ist es eine schlechte Praxis, Methoden in JSON einzufügen, da Sie Ihre Client-Server-Interaktion möglicherweise nicht gut modelliert haben. Wenn Sie JSON als Datenbeschreibungssprache verwenden möchten, würde ich sagen, dass Sie durch das Einbetten von Methoden in Schwierigkeiten geraten könnten, da einige JSON-Parser nur mit Blick auf die Datenbeschreibung geschrieben wurden und möglicherweise keine Methodendefinitionen in der Struktur unterstützen.

Der Wikipedia-JSON-Eintrag ist ein gutes Argument dafür, Methoden nicht in JSON aufzunehmen, und führt Sicherheitsbedenken an:

Wenn Sie der Quelle des Textes nicht absolut vertrauen und Text analysieren und akzeptieren müssen, der nicht streng JSON-kompatibel ist, sollten Sie eval () vermeiden und stattdessen JSON.parse () oder einen anderen JSON-spezifischen Parser verwenden. Ein JSON-Parser erkennt nur JSON-Text und lehnt anderen Text ab, der böswilliges JavaScript enthalten könnte. In Browsern, die native JSON-Unterstützung bieten, sind JSON-Parser auch viel schneller als eval. Es wird erwartet, dass die native JSON-Unterstützung im nächsten ECMAScript-Standard enthalten sein wird.

harschware
quelle
2
Möglicherweise verwenden Sie den Begriff JSON umgangssprachlich, aber offiziell ist "JSON" ein ECMA-Standard, der keine zu codierenden Funktionsobjekte enthält. Es sollte keine Unklarheit darüber geben, auf welche Funktionen Sie sich beziehen, wenn Sie "JSON" sagen - das ist der springende Punkt bei einem Standard.
Mark E. Haase
Einverstanden, dass das heute wahr ist. Ich habe keine Quelle zum Zitieren, aber ich glaube, JSON war ein Begriff, der geprägt wurde, bevor ECMA in das Javascript-Spiel kam, und bevor JSON ein Standardformat für den Datenaustausch war ... daher habe ich den Begriff "weiterentwickelt" verwendet
harschware
@harschware Laut RFC 4627 wurde JSON aus ECMA hergestellt.
Jenna Sloan
9

Lassen Sie uns eine der Spezifikationen zitieren - http://tools.ietf.org/html/rfc7159#section-12

In der JSON-Formatspezifikation (JavaScript Object Notation) wird Folgendes angegeben :

JSON ist eine Teilmenge von JavaScript, schließt jedoch Zuweisung und Aufruf aus.

Da die JSON-Syntax aus JavaScript entlehnt ist, kann die Funktion "eval ()" dieser Sprache zum Parsen von JSON-Texten verwendet werden. Dies stellt im Allgemeinen ein inakzeptables Sicherheitsrisiko dar, da der Text
ausführbaren Code zusammen mit Datendeklarationen enthalten kann
. Die gleiche Überlegung gilt für die Verwendung von eval () - ähnlichen Funktionen in jeder anderen Programmiersprache, in der JSON-Texte
der Syntax dieser Sprache entsprechen.

Alle Antworten, die besagen, dass Funktionen nicht Teil des JSON-Standards sind, sind also korrekt.

Die offizielle Antwort lautet: Nein, es ist nicht gültig, Funktionen in JSON-Ergebnissen zu definieren!


Die Antwort könnte ja sein, weil "Code ist Daten" und "Daten sind Code". Selbst wenn JSON als sprachunabhängiges Datenserialisierungsformat verwendet wird, funktioniert das Tunneln von "Code" durch andere Typen.

Eine JSON-Zeichenfolge kann verwendet werden, um eine JS-Funktion zur Ausführung an den clientseitigen Browser zu übergeben.

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

Dies führt zu Fragen wie: " Ausführen von als Zeichenfolge gespeichertem JavaScript-Code ".

Seien Sie darauf vorbereitet, das Flag "eval () ist böse" zu hissen und das Flag "Funktionen nicht durch JSON tunneln" daneben zu platzieren.

Jens A. Koch
quelle
7

Soweit ich weiß, ist es nicht Standard. Ein kurzer Blick auf http://json.org/ bestätigt dies.

jldupont
quelle
4

Nein, definitiv nicht.

Wenn Sie einen anständigen JSON-Serializer verwenden, können Sie eine solche Funktion nicht serialisieren. Es ist ein gültiges OBJEKT, aber kein gültiger JSON. Unabhängig von der Absicht dieser Website wird kein gültiger JSON gesendet.

jvenema
quelle
2
Ich benutze JSON-Lib und halte es für einen großartigen Serializer. Auf der [Verwendungsseite] (json-lib.sourceforge.net/usage.html) können Sie sehen, dass Funktionen
einwandfrei
Interessant ... das habe ich noch nie gesehen. Es ist definitiv nicht zu spezifizieren ( json.org gibt ausdrücklich an, dass JSON sprachunabhängig ist, welche Funktionsdefinitionen nicht sind), aber dennoch interessant.
Jvenema
Es ist lustig, dass es sprachunabhängig sein soll, aber JSON steht für JavaScript Object Notation hmm seltsam ..
Nate-Wilkins
3

JSON schließt Funktionen ausdrücklich aus, da es sich nicht um eine reine JavaScript-Datenstruktur handelt (trotz des JS im Namen).

Tatu Ulmanen
quelle
3

Eine kurze Antwort lautet NEIN ...

JSON ist ein Textformat, das vollständig sprachunabhängig ist, jedoch Konventionen verwendet, die Programmierern der C-Sprachfamilie bekannt sind, darunter C, C ++, C #, Java, JavaScript, Perl, Python und viele andere. Diese Eigenschaften machen JSON zu einer idealen Datenaustauschsprache.

Schauen Sie sich den Grund an, warum:

Beim Datenaustausch zwischen einem Browser und einem Server können die Daten nur Text sein.

JSON ist Text, und wir können jedes JavaScript-Objekt in JSON konvertieren und JSON an den Server senden.

Wir können auch jeden vom Server empfangenen JSON in JavaScript-Objekte konvertieren.

Auf diese Weise können wir mit den Daten als JavaScript-Objekte arbeiten, ohne komplizierte Analyse und Übersetzungen.

Aber warte ...

Es gibt immer noch Möglichkeiten, Ihre Funktion zu speichern. Dies wird allgemein nicht empfohlen , ist aber dennoch möglich:

Wir sagten, Sie können ein string... wie wäre es dann, wenn Sie Ihre Funktion in einen String konvertieren?

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

Dann können Sie Daten mit JSON.stringify(data)und dann mit JSON.parseanalysieren, um sie zu analysieren (falls dieser Schritt erforderlich ist) ...

Und eval , um eine Zeichenfolgenfunktion auszuführen (vorher müssen Sie nur wissen, dass eval weithin nicht empfohlen wird):

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

Durch die Verwendung von NodeJS (CommonJS-Syntax) konnte ich diese Art von Funktionalität zum Laufen bringen. Ursprünglich hatte ich nur eine JSON-Struktur in einer externen JS-Datei, aber ich wollte, dass diese Struktur eher eine Klasse ist, mit Methoden, über die entschieden werden kann Laufzeit.

Die Erklärung von 'Executor' in myJSON ist nicht erforderlich.

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

module.exports = {
    init: () => { return { ...myJSON, "Executor": (first, last) => { return first + last } } }
}
Mitchell Spangler
quelle
-3

Funktionsausdrücke im JSON sind vollständig möglich. Vergessen Sie jedoch nicht, sie in doppelte Anführungszeichen zu setzen. Hier ist ein Beispiel aus dem Design der noSQL-Datenbank:

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

Eimantas Pėlikis
quelle
Die Frage betrifft eine Funktion, keine Zeichenfolge. JSON unterstützt Zeichenfolgenwerte, jedoch keine Funktionen. Siehe Mikes Antwort für Details
jannis
@ jannis es ist aber möglich. wenn Sie eine selbstaufrufende Funktion wie hinzufügen. Die Leute hier kennen die Antwort anscheinend einfach nicht.
Roj
-4

Obwohl eval nicht empfohlen wird, funktioniert dies:

<!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>
pascati
quelle
1
Abgestimmt, weil es im Beispiel nicht erforderlich ist, HTML zu verwenden. Dies ist ein 5 Jahre alter Codierungsstil. Es fehlt ein Anführungszeichen. JSON-Dateien sollten keine Funktionen enthalten, wenn sie nicht serialisiert oder gespeichert werden können a no sql DB,
Martijn Scheffer
-5

Lassen Sie die Anführungszeichen weg ...

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

a.b();
Clif Collins
quelle
Dies ist JavaScript, die Frage stellt sich nach JSON.
Quentin