Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support for Decimal (monetary) data #1519

Closed
cyberphone opened this issue Apr 2, 2018 · 16 comments
Closed

Support for Decimal (monetary) data #1519

cyberphone opened this issue Apr 2, 2018 · 16 comments

Comments

@cyberphone
Copy link

Related to: #1517

Here is a printout from Open Banking in the UK. "Amount" is the field of interest.

HTTP/1.1 200 OK
x-fapi-interaction-id: 93bac548-d2de-4546-b106-880a5018460d
Content-Type: application/json
 
{
  "Data": {
    "DirectDebit": [
      {
        "AccountId": "22289",
        "DirectDebitId": "DD03",
        "MandateIdentification": "Caravanners",
        "DirectDebitStatusCode": "Active",
        "Name": "Towbar Club 3 - We Love Towbars",
        "PreviousPaymentDateTime": "2017-04-05T10:43:07+00:00",
        "PreviousPaymentAmount": {
          "Amount": "0.57",
          "Currency": "GBP"
        }
      }
    ]
  },
  "Links": {
    "Self": "https://api.alphabank.com/open-banking/v2.0/accounts/22289/direct-debits/"
  },
  "Meta": {
    "TotalPages": 1
  }
}
@MikeRalphson
Copy link
Member

In that example, amount appears to be a string type.

@cyberphone
Copy link
Author

I would rather say it is mapped to a string because there is no Decimal type in JSON in the same way as there is no DateTime type either.

W3C's Payment Request uses the same approach:
https://www.w3.org/TR/payment-request/#paymentcurrencyamount-dictionary

AFAICT, this is the de-facto standard for JSON and "money"/Decimal.

@MikeRalphson
Copy link
Member

And the actual issue with the OpenAPI specification is?

@cyberphone
Copy link
Author

cyberphone commented Apr 2, 2018

Adding support for the Decimal/monetary data type.

My current implementation:

/**
 * Read a BigDecimal property.<p>
 * Note: Since JSON does not support a native BigDecimal type, 
 * this method builds on <i>mapping</i>.</p>
 * @param name Property
 * @param decimals Required number of fractional digits or <b>null</b> if unspecified
 * @return Java <code>BigDecimal</code>
 * @throws IOException For syntax errors
 * @see JSONObjectWriter#setBigDecimal(String, BigDecimal, Integer)
 */
public BigDecimal getBigDecimal(String name, Integer decimals) throws IOException {
    return parseBigDecimal(getString(name), decimals);
}

The Decimal data type usually do not support "Scientific" notation.

@MikeRalphson
Copy link
Member

Do you mean as a new type (which would not be supported by JSON or JSON schema) or as a new format?

@cyberphone
Copy link
Author

cyberphone commented Apr 2, 2018

I mean something along the lines of dateTime which I guess is a predefined OpenAPI data type.

@MikeRalphson
Copy link
Member

MikeRalphson commented Apr 2, 2018

Your use of the words "I guess" does worry me slightly. Can I ask you to read the sections of the spec related to data types and formats if you have not already done so?

@cyberphone
Copy link
Author

cyberphone commented Apr 2, 2018

Sure, I'm unarguable NOT an expert on OpenAPI and JSON Schema. I did though read the table of data types: https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.1.md#data-types
I found dateTime and saw that it is mapped into RFC3339 formatted "strings".

I would reuse that idea for Decimal unless there is something fundamentally wrong with doing that. The W3C folks' format specification would probably suffice.

@darrelmiller
Copy link
Member

@cyberphone Yes, the specification suggests to use the format date-time along with type string to represent the common language type DateTime. Adding a new format for decimal that could be applied to the underlying type string is definitely something we would consider adding to the format registry. But I would also say that it would be perfectly valid to have a description that said type: number and format: decimal. The type is indicating what native JSON Schema type has been chose for the wire format, and format property is layering some additional semantics onto that assist tooling with the translation.

@handrews
Copy link
Member

handrews commented Apr 2, 2018

@cyberphone suport for decimals as strings, which would be implemented as {"type": "string", "format": "decimal"} or something very similar (because there is no way to control the relevant behavior as a JSON number) is proposed as json-schema-org/json-schema-vocabularies#45

It is literally waiting for someone who has knowledge of this area to be willing to write a PR. No one objects to it, but I'm sure there are subtleties here so I'm not comfortable writing a PR for it. Sadly, very few other people volunteer to write PRs for JSON Schema.

I would love to also have {"type": "number", "format": "decimal"} as an option if a reasonable spec can be written that works with the data model and not with the JSON text. As noted repeatedly, JSON is specified on a data model, not on JSON text (or octet stream or however you want to think about it).

@cyberphone
Copy link
Author

@darrelmiller For me who is neither an expert on OpenAPI nor on JSON Schema, but rather "fluent" in JSON, do you mean that you would consider using JSON Number as wire format? I would check that with tool vendors before putting that in concrete. The three (individually created) examples I provided, all took the JSON String path. There is probably a reason for that.

@darrelmiller
Copy link
Member

@cyberphone Yes. Here is the ANBF grammar for how to serialize a JSON Number over the wire in UTF-8 text.

And your last comment gets to the heart of the matter. OpenAPI is not in the business of telling people how to serialize data. That is the job of media type specifications. We are in the business of trying to describe in a platform independent manner what people chose to do.

@cyberphone
Copy link
Author

@darrelmiller Your colleges at the ".NET division" serializes a BigInteger as:

"myBigInteger":{"_bits":[1156841472,1164153218],"_sign":1}

@cyberphone
Copy link
Author

cyberphone commented Apr 2, 2018

Although maybe of limited interest to you, there is a JSON clear text signature specification in the workings which (for portability reasons), builds on I-JSON and ECMAScript serialization of JSON primitives:
https://tools.ietf.org/id/draft-erdtman-jose-cleartext-jws-00.html

The alternative to that is dressing the entire JSON object in Base64 which is making the "API" rather indirect.

@cyberphone
Copy link
Author

Just to see that we are on the same page with respect to tool support. Standard integers like implemented in for example Java and C# have:

  • Different syntax compared to a Decimal
  • Different storage compared to a Decimal
  • Different numeric range compared to a Decimal

That is, Integer and Decimal cannot readily make use of the same decoder/parser.

To make this feasible Decimal must be identified as a distinct data type. I.e. "mapped".

Do you agree with the above?

If you do, we are talking about saving 2 bytes (the quotes) and keeping "purity" (aka data model).

Since purity will only exist on the wire, we are effectively down to the 2 byte issue. However, saving 2 bytes comes at a cost: limited compatibility with JavaScript as well as with existing practices for open systems.

The decision is yours.

@MikeRalphson
Copy link
Member

Because we support the JSON data types only, this proposal is being tracked for adding a new format to the proposed OAS/JSON-Schema formats registry. See json-schema-org/json-schema-spec#845

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants