└── README.md /README.md: -------------------------------------------------------------------------------- 1 | # Extended Numeric Data Types Compliant with I-JSON 2 | 3 | *I-JSON [[RFC7493](https://tools.ietf.org/html/rfc7493)] defines rules which enable 4 | interoperability between between different implementations. Although useful, 5 | many applications depend on extended numeric data which currently is dealt with in 6 | non-standard ways. This document describes some of the more common variants, 7 | with the goal of eventually establishing some kind of standard, be it de-facto or real.* 8 | 9 | ## The Problem in a Nutshell 10 | The following JSON object highlights some of the issues with JSON numbers: 11 | ```json 12 | { 13 | "giantNumber": 1.4e+9999, 14 | "payMeThis": 26000.33, 15 | "int64Max": 9223372036854775807 16 | } 17 | ``` 18 | - `giantNumber` does not generally parse but could still be usable in certain contexts 19 | - `payMeThis` is probably not meant to be processed by a system based on traditional floating point due to potential *rounding errors* 20 | - `int64Max` parses in all JSON systems but *loses precision* using ECMAScript's `JSON.parse()` 21 | 22 | ## Core Extension Mechanism 23 | Since I-JSON numbers are constrained by IEEE-754 double precision, extended numeric data 24 | types **must** in this specification be enclosed within double quotes, i.e. have JSON String syntax, 25 | permitting basic parsing and serialization of extended data types by *virtually any* JSON tool: 26 | ```json 27 | { 28 | "giantNumber": "1.4e+9999" 29 | } 30 | ``` 31 | 32 | ## Recognizing and Processing Extended Numeric Data Types 33 | A remaining issue is how a JSON parser can know how to recognize and process 34 | extended numeric data types. Fortunately, there are multiple solutions for that. 35 | Below is a *programmatic* variant (here expressed in ECMAScript). relying on 36 | name conventions between sender and receiver: 37 | ```javascript 38 | var obj = JSON.parse('{"giantNumber": "1.4e+9999"}'); 39 | var biggie = new BigNumber(obj.giantNumber); 40 | ``` 41 | In a *declarative* system, data types are usually resolved automatically like in this Java sample: 42 | ```java 43 | class MyObject { 44 | String type; 45 | BigInteger serialNumber; 46 | } 47 | ``` 48 | 49 | ## Extended Numeric Data Types 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 |
TypeDescriptionRange       JSON Syntax *      
LongSigned 64-bit integer-9223372036854775808 to 92233720368547758070|-?[1-9][0-9]*
UlongUnsigned 64-bit integer0 to 184467440737095516150|[1-9][0-9]*
BigIntegerArbitrary large signed integer-Arbitrary to Arbitrary0|-?[1-9][0-9]*
BigDecimalArbitrary large decimal number-Arbitrary to Arbitrary-?[0-9]+(\.[0-9]+)?(e(-|\+)[0-9]+)?
MoneyDecimal number expressing money-Sufficient to Sufficient-?[1-9][0-9]*\.[0-9]+
58 | 59 | \* Minus the double quotes. 60 | 61 | *Sufficient* denotes earthly monetary sums. 62 | 63 | ## Existing Solutions 64 | A few existing solutions have been investigated. 65 | 66 | ### Java JSON-B 67 | JSON-B currently uses *Adaptive Notation* where the actual value determines if it is to be serialized as a 68 | JSON Number or be embedded in a JSON String: 69 | ```json 70 | { 71 | "BigDecimal.large": "1E+999", 72 | "BigDecimal.small": 1, 73 | "BigInteger.large": "240777489003222785532321", 74 | "BigInteger.small": 1, 75 | "Long.large": 9223372036854775807, 76 | "Long.small": 1 77 | } 78 | ``` 79 | This scheme is with the exception of "Long.large" compatible with `JSON.parse()`; 80 | 81 | ### Json.NET 82 | Json.NET doesn't seem to have any global option governing number serialization. 83 | The defaults are: 84 | ```json 85 | { 86 | "Decimal.large": 3777777447789999999445.678997, 87 | "Decimal.small": 1.0, 88 | "BigInteger.large": 240777489003222785532321, 89 | "BigInteger.small": 1, 90 | "Long.large": 9223372036854775807, 91 | "Long.small": 1 92 | } 93 | ``` 94 | This is not compliant with `JSON.parse()`; 95 | 96 | ### bignumber.js 97 | The NPM https://www.npmjs.com/package/bignumber.js relies on 98 | strings for BigNumber JSON serialization and parsing. 99 | 100 | ### W3C Payment Request 101 | The W3C Payment Request API defines a monetary amount as 102 | ```WebIDL 103 | dictionary PaymentCurrencyAmount { 104 | required DOMString currency; 105 | required DOMString value; 106 | }; 107 | ``` 108 | where `value` is a decimal number. The `DOMString` declarator means that the value is 109 | to be expressed as a JSON/ECMAScript String. 110 | 111 | ### Open Banking UK 112 | The following JSON extract from the Open Banking API shows that monetary 113 | amounts are expressed as decimal numbers enclosed in strings: 114 | ```json 115 | { 116 | "amount": "259.99", 117 | "currency": "GBP" 118 | } 119 | ``` 120 | 121 | ### Twitter 122 | The Tweet Object shows the downside of not having a unified way of dealing with big numbers: 123 | ```json 124 | { 125 | "created_at": "Thu Apr 06 15:24:15 +0000 2017", 126 | "id": 850006245121695744, 127 | "id_str": "850006245121695744", 128 | "text": "This is what I'm saying :-)", 129 | "user": {}, 130 | "entities": {} 131 | } 132 | ``` 133 | 134 | 135 | V0.12 136 | --------------------------------------------------------------------------------