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

Values of the Decimal type get marshaled to JSON as strings, not numbers #21

Closed
kostix opened this issue Jan 22, 2016 · 7 comments
Closed

Comments

@kostix
Copy link

kostix commented Jan 22, 2016

This line wraps the string representation of a value into double quotes which get transferred "as is" into the resulting JSON representation.

While I understand that a package is free to pick any "on-the-wire" representation for the values of the types it works with, I would make a claim that the selected approach is incorrect: the JSON spec defines the representation for "numbers" -- which includes both "plain" integers and floating-point values in the scientific notation, and the Decimal type provided by this package represents numbers, so I would expect it to serialize into JSON as numbers as well.

The rationale is that a receiving end for JSON representations serialized from Decimal values handled by this package is not necessarily written using the same package (or even in Go), so it naturally expects to parse these representations to whatever numeric type it supports -- be it floats, Java's BigDecimal, .NET's decimal and so on. Currently we either rely on some sloppiness of the receiver's decoder (for instance, the Json.Net library is happy to parse whatever this package produces into decimals) or require custom unmarshaling.

Actually the inconsistency I'm talking about was caught by the testing code in one of my packages -- which tested JSON serialization of whatever stuff my package generates -- after I converted its parts which work with amounts of money to use Decimal rather than stock float64: floats were marshaled as numbers, and Decimals suddenly got double-quoted (while containing the same string representations as floats).

TL;DR
I think that Decimals should be marshaled to JSON as numbers, not as strings.

@vadimg
Copy link
Contributor

vadimg commented Jan 29, 2016

I followed Python's practices on this matter. Python's simplejson package serializes decimal.Decimals as strings, so this is why I chose to do so as well.

If I had to guess a reason for it, I would say that it's safer: there is no chance someone on the other end of the wire could use the default behavior of most JSON deserializers and deserialize the decimal into a float, thus losing precision or introducing rounding errors.

@kostix
Copy link
Author

kostix commented Jan 29, 2016

If I had to guess a reason for it, I would say that it's safer: there
is no chance someone on the other end of the wire could use the
default behavior of most JSON deserializers and deserialize the
decimal into a float, thus losing precision or introducing rounding
errors.

Fair enough, thanks.

I think in my case I'll go with some workaround--custom type for
serialization or even something like

type Dec struct {
    decimal.Decimal
}

Since I'm using your package for working with money, I'm not afraid of
precision/rounding problems as I know the consumer of my data
uses the .NET's decimal type for the values marshaled from those
of your decimal.Decimal type.

@RoseEnd
Copy link

RoseEnd commented Apr 2, 2020

Please open a branch or configure it in some way so that values of decimal type can be grouped into JSON as numbers instead of strings, which is not friendly to cross language interaction

@stringy05
Copy link

For the next person who comes along with a "shopspring decimal as number in JSON" search, this behaviour is now configurable:

	decimal.MarshalJSONWithoutQuotes = true

@risentveber
Copy link

But seems like one needs more precise control over it - maybe one should need configurability for this via JSON tag options e.g? Because the global state is evil as all we know.

@alessandrozucca-p
Copy link

alessandrozucca-p commented May 17, 2024

But seems like one needs more precise control over it - maybe one should need configurability for this via JSON tag options e.g? Because the global state is evil as all we know.

I agree with the comment above, having a non global way of setting this configuration would be preferable.

We encounter an issue where a dependency of a dependency has changed that value and broke a service that was expecting the decimal to be encoded as a string

See the comment below as reference: dolthub/go-mysql-server@b1d1581#commitcomment-142143687

By the way Thank you for implementing this library, has been very useful!

alessandrozucca-p referenced this issue in dolthub/go-mysql-server May 24, 2024
@alessandrozucca-p
Copy link

@nicktobey (from go-mysql-server) has brought to my attention that there is a possible solution being discussed in #206

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

6 participants