web-dev-qa-db-fra.com

Est-il valide de définir des fonctions dans les résultats JSON?

Une partie de la réponse JSON d'un site Web contenait ceci (... ajouté pour contexte):

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

L'ajout de fonctions anonymes à JSON est-il valide? Je m'attendrais à chaque fois que vous accédez à 'time' pour renvoyer une valeur différente.

97
Zachary Scott

Non.

JSON est uniquement destiné à être un langage de description de données. Comme indiqué sur http://www.json.org , il s'agit d'un "format d'échange de données léger". - pas un langage de programmation.

Pour http://en.wikipedia.org/wiki/JSON , les "types de base" supportés sont les suivants:

  • Nombre (entier, réel ou virgule flottante)
  • String (Unicode entre guillemets doubles avec une barre oblique inversée)
  • Boolean (vrai et faux)
  • Tableau (une séquence ordonnée de valeurs, séparées par des virgules et placées entre crochets)
  • Object (collection de clés: paires de valeurs, séparées par des virgules et entourées d'accolades)
  • null
100
Mike

Le problème est que JSON en tant que langage de définition de données a évolué à partir de JSON en tant que notation d'objet JavaScript. Puisque Javascript prend en charge eval sur JSON, il est légitime de placer du code JSON dans JSON (dans ce cas d'utilisation). Si vous utilisez JSON pour transmettre des données à distance, alors je dirais que c'est une mauvaise pratique de mettre des méthodes dans le JSON car vous n'avez peut-être pas bien modélisé votre interaction client-serveur. De plus, si vous souhaitez utiliser JSON comme langage de description de données, vous risquez de vous ennuyer en incorporant des méthodes, car certains analyseurs JSON ont été écrits avec pour seule description les données et peuvent ne pas prendre en charge les définitions de méthodes dans la structure.

entrée JSON dans Wikipedia justifie la non-inclusion des méthodes dans JSON, en invoquant des problèmes de sécurité:

Sauf si vous avez absolument confiance en la source du texte et si vous avez besoin d'analyser et d'accepter du texte non conforme à JSON, évitez eval () et utilisez plutôt JSON.parse () ou un autre analyseur spécifique à JSON. Un analyseur JSON reconnaîtra uniquement le texte JSON et rejettera tout autre texte pouvant contenir du code JavaScript malveillant. Dans les navigateurs prenant en charge JSON natif, les analyseurs syntaxiques JSON sont également beaucoup plus rapides que eval. Le support JSON natif devrait être inclus dans le prochain standard ECMAScript.

16
harschware

Ce n'est pas standard pour autant que je sache. Un rapide coup d'œil sur http://json.org/ le confirme.

7
jldupont

Citons l'une des spécifications - http://tools.ietf.org/html/rfc7159#section-12

La spécification de format d'échange de données JSON (JavaScript Object Notation) indique:

JSON est un sous-ensemble de JavaScript mais exclut les affectations et les invocations.

La syntaxe de JSON étant empruntée à JavaScript, il est possible d'utiliser la fonction "eval ()" de ce langage pour analyser les textes JSON. Ceci constitue généralement un risque inacceptable pour la sécurité, car le texte
pourrait contenir du code exécutable avec des déclarations de données
. La même considération s'applique à l'utilisation de fonctions de type eval () dans tout autre langage de programmation dans lequel les textes JSON sont conformes à celui-ci.
syntaxe du langage.

Ainsi, toutes les réponses qui indiquent que les fonctions ne faisant pas partie de la norme JSON sont correctes.

La réponse officielle est: Non, il n'est pas valide de définir des fonctions dans les résultats JSON!


La réponse pourrait être oui, car "code is data" et "data is code". Même si JSON est utilisé comme format de sérialisation des données indépendant du langage, un tunneling de "code" par le biais d'autres types fonctionnera.

Une chaîne JSON peut être utilisée pour transmettre une fonction JS au navigateur côté client en vue de son exécution.

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

Cela conduit à des questions comme: Comment " Exécuter le code JavaScript stocké sous la forme d'une chaîne ".

Préparez-vous à relever le drapeau "eval () is evil" et à coller le drapeau "Ne pas tunneler par le biais de JSON" à côté.

7
Jens A. Koch

Non, certainement pas.

Si vous utilisez un sérialiseur JSON correct, il ne vous laissera pas sérialiser une telle fonction. C'est un OBJECT valide, mais pas un JSON valide. Quelle que soit l'intention de ce site Web, il n'envoie pas de code JSON valide.

4
jvenema

JSON exclut explicitement les fonctions car il ne s'agit pas d'une structure de données exclusivement JavaScript (malgré le nom JS).

3
Tatu Ulmanen

Une réponse courte est NO ...

JSON est un format de texte totalement indépendant du langage mais qui utilise des conventions bien connues des programmeurs de la famille des langages C, notamment C, C++, C #, Java, JavaScript, Perl, Python et bien d’autres. Ces propriétés font de JSON un langage d'échange de données idéal.

Regardez la raison pour laquelle:

Lors de l'échange de données entre un navigateur et un serveur, les données ne peuvent être que du texte.

JSON est un texte, et nous pouvons convertir n'importe quel objet JavaScript en JSON et envoyer JSON au serveur.

Nous pouvons également convertir n'importe quel JSON reçu du serveur en objets JavaScript.

De cette façon, nous pouvons utiliser les données sous forme d'objets JavaScript, sans analyse ni traduction compliquées.

Mais attendez ...

Il y a toujours des façons de stocker votre fonction, c'est largement non recommandé à cela, mais toujours possible:

Nous avons dit, vous pouvez enregistrer un string... que diriez-vous de convertir votre fonction en chaîne alors?

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

Vous pouvez ensuite stringifier les données en utilisant JSON.stringify(data), puis en utilisant JSON.parse Pour les analyser (si cette étape est nécessaire) ...

Et eval pour exécuter une fonction de chaîne (avant de le faire, laissez-vous savoir en utilisant eval, ce qui n'est pas recommandé):

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

En utilisant NodeJS (syntaxe commonJS), j'ai pu utiliser ce type de fonctionnalité. À l'origine, je n'avais qu'une structure JSON dans un fichier JS externe, mais je voulais que cette structure soit davantage une classe, avec des méthodes pouvant être définies à temps d'exécution.

La déclaration de "l'exécuteur" dans myJSON n'est pas requise.

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

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