web-dev-qa-db-fra.com

Pourquoi voudriez-vous utiliser une chaîne en JSON pour représenter un nombre décimal

Certaines API, comme API Paypal , utilisent un type de chaîne en JSON pour représenter un nombre décimal. Alors "7.47" au lieu de 7.47.

Pourquoi/quand cela serait-il une bonne idée d'utiliser le type de valeur de nombre json? Autant que je sache, le type de valeur numérique permet une précision infinie ainsi qu'une notation scientifique.

36
kag0

La principale raison de transférer des valeurs numériques dans JSON sous forme de chaînes est d'éliminer toute perte de précision ou toute ambiguïté dans le transfert.

Il est vrai que la spécification JSON ne spécifie pas de précision pour les valeurs numériques. Cela ne signifie pas que les nombres JSON ont une précision infinie. Cela signifie que la précision numérique n'est pas spécifiée, ce qui signifie que les implémentations JSON sont libres de choisir la précision numérique qui convient à leur implémentation ou à leurs objectifs. C’est cette variabilité qui peut poser problème si votre application a des exigences de précision spécifiques.

La perte de précision n'apparaît généralement pas dans le codage JSON de la valeur numérique (1,7 correspond à Nice et est succincte), mais se manifeste dans l'analyse JSON et les représentations intermédiaires du destinataire. Une fonction d'analyse JSON analyserait assez raisonnablement 1.7 en un nombre à virgule flottante double précision IEEE. Toutefois, les représentations de longueur finie/précision finie se heurteront toujours à des nombres impossibles à représenter avec précision. Les nombres irrationnels (comme pi et e) ne peuvent jamais être représentés avec précision dans un système fini. 1.7 a une représentation finie en notation décimale (base 10), mais en binaire (base 2), il s'agit d'un nombre irrationnel - une série infinie de chiffres.

Donc, analyser 1.7 dans un nombre à virgule flottante en mémoire, puis imprimer le nombre retournera probablement quelque chose comme 1.69 - pas 1.7.

Les consommateurs de la valeur JSON 1.7 pourraient utiliser des techniques plus sophistiquées pour analyser et conserver la valeur en mémoire, comme l’utilisation d’un type de données à point fixe ou d’un type de données "string int" avec une précision arbitraire, sans que cela ne supprime entièrement le spectre de perte de précision dans la conversion pour certains nombres. Et la réalité est que très peu d'analyseurs JSON s'embarrassent avec des mesures aussi extrêmes, car les avantages dans la plupart des situations sont faibles, les coûts en mémoire et en processeur élevés.

Donc, si vous souhaitez envoyer une valeur numérique précise à un consommateur et que vous ne voulez pas la conversion automatique de la valeur en représentation numérique interne typique, votre meilleur choix est d'envoyer la valeur numérique sous forme de chaîne et d'indiquer au consommateur exactement comment cette chaîne devrait être traitée si et quand des opérations numériques doivent être effectuées dessus.

Par exemple: dans certains producteurs JSON (JRuby, par exemple), les valeurs BigInteger sont automatiquement transmises au format JSON sous forme de chaînes, en grande partie parce que la plage et la précision de BigInteger sont beaucoup plus grandes que le flottant à double précision IEEE. Réduire la valeur de BigInteger en double afin de générer un résultat numérique JSON entraîne souvent la perte de chiffres significatifs.

De plus, la spécification JSON ( http://www.json.org/ ) indique explicitement que les NaN et les infinités (INF) ne sont pas valides pour les valeurs numériques JSON. Si vous devez exprimer ces éléments marginaux, vous ne pouvez pas utiliser de numéro JSON. Vous devez utiliser une chaîne ou une structure d'objet.

Enfin, un autre aspect peut conduire à choisir d’envoyer des données numériques sous forme de chaînes: contrôle du formatage de l’affichage. Les zéros au début et à la fin ne sont pas significatifs pour la valeur numérique. Si vous envoyez la valeur numérique JSON 2.10 ou 004, après la conversion en forme numérique interne, elles seront affichées sous la forme 2.1 et 4.

Si vous envoyez des données qui seront directement affichées à l'utilisateur, vous voudrez probablement que vos chiffres d'argent soient bien alignés sur l'écran, alignés avec des décimales. Une façon de le faire est de charger le client de formater les données pour les afficher. Une autre façon de procéder consiste à demander au serveur de formater les données à afficher. Il est peut-être plus simple pour le client d'afficher des éléments à l'écran, mais cela peut rendre l'extraction de la valeur numérique de la chaîne difficile si le client doit également effectuer des calculs sur les valeurs.

49
dthorpe

Version résumée

En citant la réponse de @ dthorpe, je pense que c’est le point le plus important:

De plus, la spécification JSON ( http://www.json.org/ ) indique explicitement que les NaN et les infinités (INF) ne sont pas valides pour les valeurs numériques JSON. Si vous devez exprimer ces éléments marginaux, vous ne pouvez pas utiliser de numéro JSON. Vous devez utiliser une chaîne ou une structure d'objet.

3
Ole