Subject: Re: [Json] JSON Schema Language is nearly done: int53

From: John Cowan <[email-masked]>
Date: Thu, 1 Aug 2019 12:08:53 -0400

On Wed, Jul 31, 2019 at 11:55 PM Ulysse Carion <[email-masked]> wrote:

The same goes for monetary data types. There are too many options, and it's
> better for the spec to stick to relatively uncontroversial things.
>

Monetary amounts need to be represented as JSON strings, or your auditors
will be down on you like a ton of bricks.  The sum of ten 0.1 values
is 0.9999999999999999, not 1.0, assuming the float64 interpretation that
essentially all JSON readers assign to JSON numbers.

John Cowan          http://vrici.lojban.org/~cowan        [email-masked]
If you have ever wondered if you are in hell, it has been said, then
you are on a well-traveled road of spiritual inquiry.  If you are
absolutely sure you are in hell, however, then you must be on the Cross
Bronx Expressway.  --Alan Feuer, New York Times, 2002-09-20

---

From: Carsten Bormann <[email-masked]>
Date: Thu, 1 Aug 2019 21:07:25 +0200

On Aug 1, 2019, at 18:08, John Cowan <[email-masked]> wrote:
> 
> Monetary amounts need to be represented as JSON strings, or your auditors will be down on you like a ton of bricks.  

That is only true if you naively equate the interchange data model with your application data model.

There is nothing wrong with interchanging currency values as floating point values if you properly process them on ingestion.  Typically, you multiply with a common denominator (such as 100 or 1000 [egyptian pounds?, or US mills as in gasoline prices]) and round to the nearest integer.

> The sum of ten 0.1 values is 0.9999999999999999, not 1.0, assuming the float64 interpretation that essentially all JSON readers assign to JSON numbers.

Right, you can’t *compute* with them as floating point values (well, you can, but you need to be even more careful with the rounding).

You still can *interchange* them as floating point values if you have enough precision (binary32 notably doesn’t for most applications; you really need binary64, and you are still limited to applications that handle less than ~ 90 Microsofts or Apples a piece and don’t need more internal decimal places at the same time).

A data definition language could contain specific support for binary floating point values used to encode decimal fractions; CDDL currently doesn’t (but support could be added using its main extension point: control operators).

Grüße, Carsten

---

From: Anders Rundgren <[email-masked]>
Date: Thu, 1 Aug 2019 21:54:27 +0200

> There is nothing wrong with interchanging currency values as floating point values if you properly process them on ingestion.  Typically, you multiply with a common denominator (such as 100 or 1000…

In this case there are standards that are interoperable with any JSON parser although you typically have to perform one or two additional operations in order to get the proper local representation:
https://www.w3.org/TR/payment-request/#dfn-valid-decimal-monetary-value

We lucky guys(?) who build our own stuff have it natively:
https://cyberphone.github.io/doc/openkeystore/javaapi/org/webpki/json/JSONObjectReader.html#getMoney-java.lang.String-java.lang.Integer%2d
mapped => "string"

Anders

---

From: Ulysse Carion <[email-masked]>
Date: Thu, 1 Aug 2019 21:39:58 -0700

Within this discussion we've seen precisely why I don't think JSL should
take on directly supporting currency-related stuff. Anders describes the
W3C's payment-request spec, which uses a string, whereas Carsten describes
the multiply-by-denominator approach, which is the one that Stripe uses:
https://stripe.com/docs/api/charges/create

I think JSL is useful without currency-specific support, just as it is
useful without int64/uint64. Better to ship fewer things well, no?

On Thu, Aug 1, 2019 at 12:54 PM Anders Rundgren <
[email-masked]> wrote:

> >> Monetary amounts need to be represented as JSON strings, or your
> auditors will be down on you like a ton of bricks.
> >
> > There is nothing wrong with interchanging currency values as floating
> point values if you properly process them on ingestion.  Typically, you
> multiply with a common denominator (such as 100 or 1000 [egyptian pounds?,
> or US mills as in gasoline prices]) and round to the nearest integer.
>
> In this case there are standards that are interoperable with any JSON
> parser although you typically have to perform one or two additional
> operations in order to get the proper local representation:
> >> The sum of ten 0.1 values is 0.9999999999999999, not 1.0, assuming the
> float64 interpretation that essentially all JSON readers assign to JSON
> numbers.
> >
> > Right, you can’t *compute* with them as floating point values (well, you
> can, but you need to be even more careful with the rounding).
> >
> > You still can *interchange* them as floating point values if you have
> enough precision (binary32 notably doesn’t for most applications; you
> really need binary64, and you are still limited to applications that handle
> less than ~ 90 Microsofts or Apples a piece and don’t need more internal
> decimal places at the same time).
> >
> > A data definition language could contain specific support for binary
> floating point values used to encode decimal fractions; CDDL currently
> doesn’t (but support could be added using its main extension point: control
> operators).
> >
> > Grüße, Carsten
> >
>
>

---

From: Anders Rundgren <[email-masked]>
Date: Fri, 2 Aug 2019 07:20:51 +0200

https://www.w3.org/TR/payment-request/#dfn-valid-decimal-monetary-value
It has been agreed upon by payment folks from Google, Microsoft, VISA, etc.
Published Open Banking API's have AFAIK adopted this scheme as well.

The previously posted link rot due an API change...
https://cyberphone.github.io/doc/openkeystore/javaapi/org/webpki/json/JSONObjectWriter.html#setMoney-java.lang.String-java.math.BigDecimal-int%2d

For those who insist that JSON Number is the only "true" way of serializing numbers in JSON, a "number" type would be the logical choice.

/anders

---

From: Carsten Bormann <[email-masked]>
Date: Fri, 2 Aug 2019 08:47:17 +0200

> On Aug 2, 2019, at 06:39, Ulysse Carion <[email-masked]> wrote:
> 
> Within this discussion we’ve seen precisely why I don't think JSL should take on directly supporting currency-related stuff. 

The more powerful data definition languages don’t need any more functionality here, e.g., in CDDL one would simply write:

decimal-monetary-value = text .regexp "-?[0-9]+(\\.[0-9]+)?”

For a data definition scheme such as JSL, which opts out of specifying subtypes of what are the common base types in programming languages, this would indeed seem to be misplaced.

Let’s see how well JSL withstands the “just this one more feature” urge…

Grüße, Carsten

---

From: Pete Cordell <[email-masked]>
Date: Fri, 2 Aug 2019 12:00:43 +0100

On 02/08/2019 05:39, Ulysse Carion wrote:
> W3C's payment-request spec, which uses a string, whereas Carsten 
> describes the multiply-by-denominator approach, which is the one that 
> Stripe uses: https://stripe.com/docs/api/charges/create
> 

A recent solution to JCR for managing an ever growing type system is to 
allow the base type to have a format URI designator with it. So JSL 
would end up looking something like:

"amount": {
    "type": "string",
    "format": 
"https://www.w3.org/TR/payment-request/#dfn-valid-decimal-monetary-value" }

The format can then be defined in separate documents.  Which layer of 
validation ensures the format is correct is an implementation detail. 
The lower layers could just ensure it's a string. Higher layers could 
ensure that the string has the correct format.

> On Thu, Aug 1, 2019 at 12:54 PM Anders Rundgren 
> <[email-masked] <mailto:[email-masked]>> 
> wrote:
> 
>      > On Aug 1, 2019, at 18:08, John Cowan <[email-masked]
>     <mailto:[email-masked]>> wrote:
>      >>
>      > There is nothing wrong with interchanging currency values as
>     floating point values if you properly process them on ingestion. 
>     Typically, you multiply with a common denominator (such as 100 or
>     1000 [egyptian pounds?, or US mills as in gasoline prices]) and
>     round to the nearest integer.
> 
>     In this case there are standards that are interoperable with any
>     JSON parser although you typically have to perform one or two
>     additional operations in order to get the proper local representation:
>      >> The sum of ten 0.1 values is 0.9999999999999999, not 1.0,
>     assuming the float64 interpretation that essentially all JSON
>     readers assign to JSON numbers.
>      >
>      > Right, you can’t *compute* with them as floating point values
>     (well, you can, but you need to be even more careful with the rounding).
>      >
>      > You still can *interchange* them as floating point values if you
>     have enough precision (binary32 notably doesn’t for most
>     applications; you really need binary64, and you are still limited to
>     applications that handle less than ~ 90 Microsofts or Apples a piece
>     and don’t need more internal decimal places at the same time).
>      >
>      > A data definition language could contain specific support for
>     binary floating point values used to encode decimal fractions; CDDL
>     currently doesn’t (but support could be added using its main
>     extension point: control operators).
>      >
>      > Grüße, Carsten
>      >

Pete.
-- 
---------------------------------------------------------------------
Pete Cordell
Codalogic Ltd
Read & write XML in C++, http://www.xml2cpp.com
---------------------------------------------------------------------

---

From: Anders Rundgren <[email-masked]>
Date: Fri, 2 Aug 2019 15:41:34 +0200

Cool!