3

I know that I should use integers for "money values" when programming. I know it's because of the 0.1 + 0.2 != 0.3 problem. But I don't know the problem well enough to know if that's a problem in data formats (like JSON) as well.

In my concrete case: should I define

type Money {
    amount: Float!
    # ...
}

or

type Money {
    amount: Int!
    # ...
}

in GraphQL?

Rudolph Gottesheim
  • 1,671
  • 1
  • 17
  • 30

2 Answers2

7

Representing Money in general is a hard problem. Handling currencies, formats, fractional vs non-fractional currencies, etc.

Modeling Money as a complex object type is often a good idea. This enables you to encode more data on the context of the monetary value. Another option is defining your own Scalar type that represents money.

A good example to look at is Shopify's GraphQL API: https://help.shopify.com/en/api/graphql-admin-api/reference/object/moneyv2

They include both currency and amount, which is defined as a Decimal scalar. Having complex objects allows you to evolve that type better over time too. Using Int or Float will be hard to evolve if you add anything like server side formatting or currency information.

XuoriG
  • 600
  • 4
  • 17
  • Thank you. Take another look at my examples. Obviously, the `Money` type would have a currency associated with it, and maybe some other fields. My question was just about the `amount` field and its type. – Rudolph Gottesheim Jun 28 '19 at 19:18
  • +1 to a custom scalar like decimal. GraphQL spec limits int support to 32 bit, which can be pretty restrictive https://spec.graphql.org/draft/#sel-HAHXRHFCBBB9FnnP – mmartinson Aug 17 '21 at 23:15
4

GraphQL itself does not perform any comparisons between resolved values. You might introduce sorting logic or something else that would require you to compare two floating point values, but this would be logic you implement yourself and so you could act accordingly. As such, the decision whether to use Float or Int should be based on the needs of clients consuming the API (or possibly other limitations like the language or database you're using on the backend) -- there are no additional considerations just because you're dealing with GraphQL.

Similarly, there's nothing about serializing or deserializing JSON that would require floating point values to be compared.

The JSON specification does not limit the size of numbers. As such, you technically might hit some language-specific limit when deserializing JSON, whether it's an integer or a floating point. But if you're working with currencies I'm guessing that's highly unlikely (for example, in JavaScript, the largest possible integer value is 9,007,199,254,740,991 versus the $100,000,000,000,000 or so in circulation of all currencies in the world.

Daniel Rearden
  • 80,636
  • 11
  • 185
  • 183