2015-05-14 16 views
14

Bedenkt man, unter Berücksichtigung verschiedener Eigenheiten der Datentypen und Lokalisierung, wie kann ein Webservice Geldwerte von und zu Anwendungen kommunizieren? Gibt es irgendwo einen Standard?Was ist der Standard für die Formatierung von Währungswerten in JSON?

Mein erster Gedanke war, einfach den Zahlentyp zu verwenden. Zum Beispiel

"amount": 1234.56 

Ich habe viele Argumente über Probleme mit einem Mangel an Präzision und Rundungsfehler zu sehen, wenn Gleitkommadaten Typen für das Geld Berechnungen mit - wir sind jedoch nur den Wert zu übertragen, nicht zu berechnen, so dass shouldn Es ist egal.

EventBrite's JSON currency specifications etwas wie folgt angeben:

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

Bravo für Fließkommawerte zu vermeiden, aber jetzt sind wir in ein anderes Problem stoßen: Was ist die größte Zahl, die wir halten können?

One comment (Ich weiß nicht, ob es wahr ist, aber scheint vernünftig) behauptet, dass, da Zahlenimplementierungen in JSON variieren, das Beste, was Sie erwarten können, ist eine 32-Bit-Ganzzahl mit Vorzeichen. Der größte Wert, den eine vorzeichenbehaftete 32-Bit-Ganzzahl enthalten kann, ist 2147483647. Wenn wir Werte in der untergeordneten Einheit darstellen, sind das 21.474.836,47 $. 21 Millionen Dollar scheinen eine riesige Zahl zu sein, aber es ist nicht unvorstellbar, dass einige Anwendungen mit einem größeren Wert arbeiten müssen. Das Problem verschärft sich bei Währungen, bei denen 1.000 der kleineren Einheiten eine größere Einheit bilden oder bei denen die Währung weniger wert ist als der US-Dollar. Zum Beispiel ist ein tunesischer Dinar in 1.000 Milim unterteilt. 2147483647 milim oder 2147483.647 TND ist $ 1.124.492.04. Es ist sogar wahrscheinlicher, dass Werte über 1 Million $ in einigen Fällen verarbeitet werden können. Ein anderes Beispiel: Die Untereinheiten des vietnamesischen Dong wurden durch die Inflation unbrauchbar gemacht, also benutzen wir einfach größere Einheiten. 2147483647 VND ist $ 98,526.55. Ich bin mir sicher, dass viele Anwendungsfälle (Bankguthaben, Immobilienwerte usw.) wesentlich höher sind. (EventBrite muss sich wahrscheinlich nicht darum sorgen, dass die Ticketpreise so hoch sind!)

Wenn wir dieses Problem umgehen, indem wir den Wert als String mitteilen, wie sollte der String formatiert werden? Unterschiedliche Länder/Gebietsschemata haben drastisch unterschiedliche Formate - verschiedene Währungssymbole, ob das Symbol vor oder nach dem Betrag auftritt, ob ein Leerzeichen zwischen dem Symbol und dem Betrag vorhanden ist oder nicht, wenn Komma oder Punkt verwendet wird, um die Dezimaltrennzeichen zu trennen werden als Tausendertrennzeichen, Klammern oder ein Minuszeichen verwendet, um negative Werte anzuzeigen, und möglicherweise mehr, die mir nicht bekannt sind.

sollten wissen, die App, welche locale/Währung es funktioniert, kommunizieren Werte wie

"amount": "1234.56" 

hin und her, und die App vertrauen richtig um die Menge zu formatieren? (Auch: sollte der Dezimalwert vermieden werden und der Wert in der kleinsten Währungseinheit angegeben werden? Oder sollte die Haupt- und Nebeneinheit in verschiedenen Eigenschaften aufgeführt sein?)

Oder sollte der Server den Rohwert und die formatierter Wert?

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

Oder sollte der Server den Rohwert und den Währungscode bereitstellen und die App formatieren lassen? "Betrag": "1234.56" "WährungCode": "USD" Ich nehme an, welche Methode verwendet wird, sollte in beiden Richtungen verwendet werden, Übertragung an und von dem Server.

Ich konnte den Standard nicht finden - haben Sie eine Antwort oder können Sie mich auf eine Ressource verweisen, die dies definiert? Es scheint ein häufiges Problem zu sein.

+1

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

Antwort

2

AFAIK, es gibt keinen "Währungsstandard" in JSON - es ist ein Standard basierend auf rudimentären Typen. Dinge, die Sie beachten sollten, ist, dass einige Währungen keinen Dezimalteil (Guinean Franc, Indonesische Rupiah) haben und einige in Tausendstel (Bahrain-Dinar) geteilt werden können - deshalb wollen Sie nicht zwei Dezimalstellen annehmen. Für den iranischen Real werden $ 2 Millionen Sie nicht weit bringen, also würde ich erwarten, dass Sie sich mit Doubles beschäftigen müssen, nicht mit ganzen Zahlen. Wenn Sie nach einem allgemeinen internationalen Modell suchen, benötigen Sie einen Währungscode, da Länder mit Hyperinflation jedes Jahr die Währungen wechseln, um den Wert auf 1.000.000 (oder 100 Millionen) zu verteilen. Historisch gesehen haben Brasilien und Iran beides getan, denke ich.

Wenn Sie eine Referenz für die Währungscodes (und ein wenig andere gute Informationen) müssen dann schauen Sie hier: https://gist.github.com/Fluidbyte/2973986

+0

Vielen Dank für Ihre Gedanken. Ich habe bereits auf einige Probleme hingewiesen. Was ich suche, ist etwas, das funktioniert. –

4

Ich weiß nicht, ob es die beste Lösung ist, aber was ich versuche jetzt geben Werte als Strings ist nur unformatierte mit Ausnahme einer Dezimalstelle, etwa so:

"amount": "1234.56" 

die App leicht, dass nicht analysieren (und wandeln es zu verdoppeln, BigDecimal, int, oder was auch immer Methode der App-Entwickler fühlt sich am besten für Gleitkommaarithmetik). Die App würde dafür verantwortlich sein, den Wert für die Anzeige nach Gebietsschema und Währung zu formatieren.

Dieses Format könnte auch andere Währungswerte aufnehmen, ob stark aufgeblasene große Zahlen, Zahlen mit drei Ziffern nach dem Komma, Zahlen ohne überhaupt Bruchwerte usw.

Natürlich ist dies bereits die App übernehmen würde kennt das Gebietsschema und die verwendete Währung (aus einem anderen Anruf, einer App-Einstellung oder lokalen Gerätewerten). Wenn diejenigen Bedarf pro Anruf angegeben werden, wäre eine weitere Option:

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

Ich bin versucht, diese in ein JSON-Objekt zu rollen, aber ein JSON-Feed mehrere Beträge für verschiedene Zwecke haben können, und dann wäre nur brauchen Einmalige Angabe von Währungseinstellungen Natürlich, wenn es aufgeführt für jede Menge variieren könnte, dann wäre es am besten, sie zusammen wie so, einzuzukapseln:

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

Ein weiterer Ansatz für fragwürdig ist der Server die rohe Menge und die formatierte Menge zu bieten. (Wenn ja, würde ich vorschlagen, es als Objekt einkapseln, statt in einem Feed mehr Eigenschaften, die alle das gleiche Konzept definieren):

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

hier mehr von der Arbeit an den Server ausgelagert. Es stellt auch die Konsistenz zwischen den verschiedenen Plattformen und Apps bei der Darstellung der Zahlen sicher und bietet gleichzeitig einen leicht analysierbaren Wert für bedingte Tests und ähnliches.

Es bleibt jedoch ein Problem - was ist, wenn die App Berechnungen durchführen und dann die Ergebnisse dem Benutzer zeigen muss? Es muss immer noch die Nummer für die Anzeige formatieren. Könnte auch mit dem ersten Beispiel am Anfang dieser Antwort gehen und der App die Kontrolle über die Formatierung geben.

Das sind meine Gedanken, zumindest. Ich konnte keine fundierten Best Practices oder Forschungen in diesem Bereich finden, daher begrüße ich bessere Lösungen oder mögliche Fallstricke, auf die ich nicht hingewiesen habe.

0

ON Dev Portal - API Guidelines - Currencies Sie interessante Anregungen finden können:

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

Es ist ein bisschen schwieriger & Format als nur eine Zeichenfolge zu erzeugen, aber ich finde, dass das die sauberste und sinnvoll ist, es zu erreichen:

  1. abkuppeln Betrag und Währung
  2. Verwendung numberJSON Typ

Hier ist das JSON-Format vorgeschlagen: 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" 
    ] 
} 

Ein weiteres questions related to currency format Recht oder zu Unrecht darauf hingewiesen, dass die Praxis mit Basiseinheiten wie eine Saite viel mehr ist:

{ 
    "price": "40.0" 
}