Quelle est la norme pour formater les valeurs de devise dans JSON?

en tenant compte des différentes bizarreries des types de données, et de la localisation, Quelle est la meilleure façon pour un service web de communiquer des valeurs monétaires à et à partir des applications? Il y a une norme quelque part?

Ma première pensée a été d'utiliser simplement le type de numéro. Par exemple,

"amount": 1234.56

j'ai vu beaucoup d'arguments sur des questions avec un manque de précision et des erreurs d'arrondi lors de l'utilisation des types de données à virgule flottante pour les calculs monétaires--cependant, nous ne transmettons la valeur, pas le calcul, donc ça ne devrait pas avoir d'importance.

spécifications des devises JSON D'EventBrite spécifier quelque chose comme ceci:

{
"currency": "USD", 
"value": 432, 
"display": ".32"
}

Bravo pour avoir évité les valeurs à virgule flottante, mais maintenant nous rencontrons un autre problème: quel est le plus grand nombre que nous pouvons retenir?

commentaire (Je ne sais pas si c'est vrai, mais semble raisonnable) prétend que, puisque les implémentations de nombre varient en JSON, le mieux que vous pouvez vous attendre est un 32-bit signé entier. La plus grande valeur qu'un entier signé de 32 bits peut contenir est 2147483647. Si nous représentons des valeurs dans l'unité mineure, c'est 21 474 836$.47. 21 millions de dollars semble comme un nombre énorme, mais il n'est pas inconcevable que certaines applications peuvent avoir besoin de travailler avec une valeur plus grande que cela. Le problème s'aggrave avec les monnaies où 1.000 de l'unité mineure font une unité majeure, ou où la monnaie vaut moins que le dollar US. Par exemple, un Dinar Tunisien est divisé en 1000 milim. 2147483647 milim, ou 2147483.647 TND est de $ 1,124,492.04. Il est encore plus probable des valeurs de plus d'un million de dollars peut être travaillé dans certains cas. Un autre exemple: les sous-unités du dong Vietnamien ont été rendues inutiles par l'inflation, alors utilisons simplement des unités majeures. 2147483647 VND est de 98 526$.55. Je suis sûr que de nombreux cas d'utilisation (soldes bancaires, valeurs immobilières, etc. sont nettement plus élevés. (EventBrite n'a probablement pas à s'inquiéter du prix des billets étant si élevé, cependant!)

si nous évitons cela problème en communiquant la valeur comme une chaîne, comment la chaîne devrait-elle être formatée? Différents pays / locales ont des formats radicalement différents-différents symboles de monnaie, si le symbole se produit avant ou après la quantité, s'il y a ou non un espace entre le symbole et la quantité, si une virgule ou une période est utilisée pour séparer la décimale, si les virgules sont utilisées comme un séparateur de milliers, les parenthèses ou un signe moins pour indiquer des valeurs négatives, et peut-être plus que je ne sais pas de.

si l'application sait avec quelle locale / devise elle travaille, communiquez des valeurs comme

"amount": "1234.56"

aller-retour, et faire confiance à l'application pour formater correctement le montant? (Aussi: faut-il éviter la valeur décimale et la valeur spécifiée en termes de plus petite unité monétaire? Ou l'unité principale et l'unité secondaire devraient-elles être énumérées dans des propriétés différentes?)

ou le serveur doit-il fournir la valeur brute et la valeur formatée?

"amount": "1234.56"
"displayAmount": ",234.56"

Ou devrait le serveur fournit la valeur brute et le code de devise, et laisser l'application le formater? "montant": "1234.56" "currencyCode": "USD" Je suppose que la méthode utilisée doit être utilisée dans les deux sens, en transmettant vers et depuis le serveur.

j'ai été incapable de trouver le standard--avez-vous une réponse, ou peut m'indiquer une ressource qui la définit? Il semble comme un problème commun.

17
demandé sur Jean-Rémy Revy 2015-05-15 02:59:08

3 réponses

je ne sais pas si c'est la meilleure solution, mais ce que j'essaie maintenant est de transmettre des valeurs comme des chaînes de caractères non formaté à l'exception d'une virgule, comme ceci:

"amount": "1234.56"

l'application pourrait facilement analyser cela (et le convertir en double, BigDecimal, int, ou n'importe quelle méthode que le développeur d'application sent le meilleur pour l'arithmétique flottante). L'application serait responsable du formatage de la valeur pour l'affichage selon la locale et la devise.

ce format pourrait accommoder d'autres les valeurs de devise, si les grands nombres fortement gonflés, les nombres avec trois chiffres après le point décimal, les nombres sans valeurs fractionnaires du tout, etc.

bien sûr, cela supposerait que l'application connaît déjà la localisation et la monnaie utilisée (à partir d'un autre appel, d'un paramètre d'application, ou de valeurs de périphérique local). Si ceux qui ont besoin d'être précisées par appel, une autre option serait:

"amount": "1234.56",
"currency": "USD",
"locale": "en_US"

je suis tenté de les rouler dans un objet JSON, mais un flux JSON peut avoir plusieurs valeurs pour différentes finalités, et il ne serait alors nécessaire de spécifier les paramètres monétaires qu'une seule fois. Bien sûr, si cela peut varier pour chaque quantité énumérée, alors il serait préférable de les encapsuler ensemble, comme ceci:

{
"amount": "1234.56",
"currency": "USD",
"locale": "en_US"
}

une autre approche discutable consiste pour le serveur à fournir la quantité brute et la quantité formatée. (Si si, je vous suggère d'encapsulation comme un objet, au lieu d'avoir plusieurs propriétés dans un flux qui définissent tous le même concept):

{
"displayAmount":",234.56",
"calculationAmount":"1234.56"
}

Ici, plus de le travail est déchargé pour le serveur. Il assure également la cohérence entre les différentes plates-formes et applications dans la façon dont les nombres sont affichés, tout en fournissant une valeur facilement analysable pour les tests conditionnels et autres.

cependant, cela laisse un problème--que se passe-t-il si l'application doit effectuer des calculs et ensuite montrer les résultats à l'utilisateur? Il devra tout de même formater le numéro pour l'afficher. Pourrait tout aussi bien aller avec le premier exemple en haut de cette réponse et de donner l'app de contrôle sur le formatage.

ce sont mes pensées, au moins. J'ai été incapable de trouver des pratiques exemplaires ou des recherches solides dans ce domaine, alors je me réjouis de trouver de meilleures solutions ou des pièges potentiels que je n'ai pas mentionnés.

4
répondu Chad Schultz 2015-05-15 18:09:37

autant que je sache, il n'y a pas de "monnaie" standard en JSON - c'est un standard basé sur rudimentaires types. Les choses que vous pourriez considérer est que certaines devises n'ont pas une partie décimale (Franc guinéen, Rupiah indonésien) et certaines peuvent être divisées en millièmes (Dinar bahreïnien)- donc vous ne voulez pas assumer deux places décimales. Pour la réalité iranienne 2 millions de dollars ne va pas vous mener loin, donc je m'attendrais à ce que vous devez traiter avec des doubles pas des entiers. Si vous êtes à la recherche pour un international général modèle alors vous aurez besoin d'un code de devise car les pays avec l'hyperinflation changent souvent des devises chaque année de deux pour diviser la valeur par 1.000.000 (ou 100 millions). Historiquement, le Brésil et L'Iran ont tous deux fait cela, je pense.

Si vous avez besoin d'une référence pour les codes des monnaies (et un peu d'autres bonnes informations), puis prendre un coup d'oeil ici: https://gist.github.com/Fluidbyte/2973986

3
répondu Paul Coldrey 2017-09-08 07:16:33

Dev Portail de l'API, les Directives sur les Monnaies vous pouvez trouver des suggestions intéressantes :

"price" : {
 "amount": 40,
 "currency": "EUR"
}

C'est un peu plus difficile à produire et format que juste une chaîne de caractères, mais j'ai l'impression que c'est le plus propre et de manière significative à atteindre :

  1. découpler le montant et la devise
  2. utiliser numberJSON tapez

voici le format JSON suggéré: https://pattern.yaas.io/v2/schema-monetary-amount.json

{
    "$schema": "http://json-schema.org/draft-04/schema#",
    "type": "object",
    "title": "Monetary Amount",
    "description":"Schema defining monetary amount in given currency.",
    "properties": {
        "amount": {
            "type": "number",
            "description": "The amount in the specified currency"
        },
        "currency": {
            "type": "string",
            "pattern": "^[a-zA-Z]{3}$",
            "description": "ISO 4217 currency code, e.g.: USD, EUR, CHF"
        }
    },
    "required": [
        "amount",
        "currency"
    ]
}

un Autre questions relatives au format de la devise fait remarquer à tort ou à raison, que la pratique ressemble beaucoup plus à une chaîne avec des unités de base:

{
    "price": "40.0"
}
1
répondu Jean-Rémy Revy 2017-08-08 16:39:00