2015-05-14 40 views
14

Tenendo conto delle varie peculiarità dei tipi di dati e della localizzazione, qual è il modo migliore per un servizio Web di comunicare i valori monetari da e verso le applicazioni? C'è uno standard da qualche parte?Qual è lo standard per la formattazione dei valori di valuta in JSON?

Il mio primo pensiero è stato semplicemente utilizzare il tipo di numero. Ad esempio

"amount": 1234.56 

ho visto molte discussioni sui problemi con una mancanza di precisione e di arrotondamento errori nell'uso floating point tipi di dati per i calcoli monetari - tuttavia, ci sono solo trasmettere il valore, non calcolando, in modo che shouldn non importa.

EventBrite's JSON currency specifications specificare qualcosa di simile:

{ 
"currency": "USD", 
"value": 432, 
"display": "$4.32" 
} 

Bravo per evitare valori in virgola mobile, ma ora ci imbattiamo in un altro problema: qual è il più grande numero possiamo tenere?

One comment (non so se è vero, ma sembra ragionevole) afferma che, dal momento che le implementazioni dei numeri variano in JSON, il meglio che puoi aspettarti è un numero intero con segno a 32 bit. Il valore più grande che un intero con segno a 32 bit può contenere è 2147483647. Se rappresentiamo valori nell'unità minore, questo è $ 21,474,836,47. $ 21 milioni sembrano un numero enorme, ma non è inconcepibile che alcune applicazioni possano aver bisogno di lavorare con un valore più grande di quello. Il problema peggiora con le valute in cui 1.000 unità minori formano un'unità principale o dove la valuta vale meno del dollaro USA. Ad esempio, un dinaro tunisino è diviso in 1.000 milim. 2147483647 milim, o 2147483.647 TND è $ 1,124,492,04. È ancora più probabile che in alcuni casi vengano utilizzati valori superiori a $ 1 milione. Un altro esempio: le sottounità dei dong vietnamiti sono state rese inutili dall'inflazione, quindi usiamo solo le unità principali. 2147483647 VND è $ 98,526,55. Sono sicuro che molti casi d'uso (saldi bancari, valori immobiliari, ecc.) Sono sostanzialmente più alti di così. (EventBrite probabilmente non deve preoccuparsi che i prezzi dei biglietti siano così alti, però!)

Se evitiamo questo problema comunicando il valore come una stringa, come deve essere formattata la stringa? Diversi paesi/località hanno formati drasticamente diversi, diversi simboli di valuta, se il simbolo si verifica prima o dopo l'importo, indipendentemente dal fatto che vi sia uno spazio tra il simbolo e l'importo, se viene utilizzata una virgola o un punto per separare il decimale, se le virgole sono usati come separatore di migliaia, parentesi o un segno meno per indicare valori negativi, e possibilmente più di cui non sono a conoscenza.

Qualora l'applicazione sapere locale/moneta si sta lavorando con, comunicare i valori come

"amount": "1234.56" 

avanti e indietro, e la fiducia l'applicazione per formattare correttamente la quantità? (Inoltre: il valore decimale deve essere evitato e il valore specificato in termini di unità monetaria più piccola? O l'unità principale e secondaria deve essere elencata in proprietà diverse?)

Oppure il server deve fornire il valore grezzo e valore formattato?

"amount": "1234.56" 
"displayAmount": "$1,234.56" 

Oppure il server deve fornire il valore grezzo e il codice valuta e lasciare che l'app lo formatti? "importo": "1234.56" "currencyCode": "USD" Presumo che qualsiasi metodo utilizzato debba essere utilizzato in entrambe le direzioni, trasmettendo da e verso il server.

Non riesco a trovare lo standard - avete una risposta o potete indicarmi una risorsa che lo definisce? Sembra un problema comune.

+1

questione connessa: https: //stackoverflow.com/questions/45222706/what-are-the-best-practices-passing-dollar-amounts-in-json –

risposta

2

AFAIK, non esiste uno standard di "valuta" in JSON - si tratta di uno standard basato su tipi rudimentali. Le cose che dovresti considerare sono che alcune valute non hanno una parte decimale (franco della Guinea, Rupia indonesiana) e alcune possono essere divise in millesimi (Dinar del Bahrain) - quindi non vuoi assumere due cifre decimali. Per il Realian iraniano $ 2 milioni non ti porterà lontano, quindi mi aspetto che tu debba occuparti di doppi e non interi. Se stai cercando un modello internazionale generale, avrai bisogno di un codice di valuta in quanto i paesi con iperinflazione spesso cambiano le valute ogni anno di due per dividere il valore di 1.000.000 (o 100 mill). Storicamente il Brasile e l'Iran hanno entrambi fatto questo, credo.

Se avete bisogno di un punto di riferimento per i codici di valuta (e un po 'di altro bene informazioni) allora date un'occhiata qui: https://gist.github.com/Fluidbyte/2973986

+0

Grazie per i vostri pensieri. Ho già segnalato una serie di problemi con alcuni approcci. Quello che sto cercando è qualcosa che funziona. –

4

Non so se è la soluzione migliore, ma quello che sto cercando ora è quello di passare solo valori come stringhe formattati ad eccezione di un punto decimale, in questo modo:

"amount": "1234.56" 

l'applicazione potrebbe facilmente passare questo (e convertirlo per raddoppiare, BigDecimal, int, o qualunque sia il metodo lo sviluppatore dell'app si sente meglio per aritmetica in virgola mobile). L'app sarebbe responsabile della formattazione del valore per la visualizzazione in base alle impostazioni internazionali e alla valuta.

Questo formato poteva ospitare altri valori di valuta, se un gran numero altamente gonfiati, numeri con tre cifre dopo la virgola, numeri senza valori frazionari a tutti, ecc

Naturalmente, questo avrebbe assunto l'applicazione già conosce le impostazioni internazionali e la valuta utilizzata (da un'altra chiamata, un'impostazione dell'app o i valori dei dispositivi locali). Se coloro che hanno bisogno di essere specificato per ogni chiamata, un'altra opzione potrebbe essere:

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

Sono tentato di rotolare questi in un unico oggetto JSON, ma un feed JSON può avere più quantità per scopi diversi, e quindi avrebbe bisogno solo di per specificare le impostazioni di valuta una volta. Naturalmente, se potesse variare per ogni importo di cui, allora sarebbe meglio per incapsulare insieme, in questo modo:

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

Un altro approccio discutibile è per il server di fornire la quantità cruda e la quantità formattato. (Se è così, vorrei suggerire incapsulare come un oggetto, invece di avere più proprietà in un feed che tutti definiscono lo stesso concetto):

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

Qui, più del lavoro non sono scaricati al server. Garantisce inoltre la coerenza tra diverse piattaforme e app nel modo in cui i numeri vengono visualizzati, fornendo comunque un valore facilmente analizzabile per test condizionali e simili.

Tuttavia, lascia un problema: cosa succede se l'app deve eseguire calcoli e quindi mostrare i risultati all'utente? Sarà comunque necessario formattare il numero per la visualizzazione. Potrebbe anche andare con il primo esempio in cima a questa risposta e dare il controllo dell'app sulla formattazione.

Questi sono i miei pensieri, almeno. Non sono riuscito a trovare solide buone pratiche o ricerche in questo settore, quindi accolgo con favore soluzioni migliori o potenziali insidie ​​che non ho indicato.

0

ON Dev Portal - API Guidelines - Currencies si possono trovare proposte interessanti:

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

è un po 'più difficile da produrre il formato & di una semplice stringa, ma sento che questo è il modo più pulito e significativa per realizzarla:

  1. importo e la valuta uncouple
  2. uso numberJSON tipo

Qui il formato JSON suggerito: 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'altra questions related to currency format rilevare destra oa ragione, che la pratica è molto più simile a una stringa con unità di base:

{ 
    "price": "40.0" 
} 
Problemi correlati