What the error means
JSON has one number type. Go has many, and encoding/json will not silently truncate. json: cannot unmarshal number 18.25 into Go struct field Order.total of type int64 means the payload carried a value with a fractional part, and the struct field cannot represent it. Go refuses rather than rounding, which is the correct behaviour for a value that might be money.
The interesting part is how the field came to be int64 in the first place. In the example, the first record has "total": 18, a whole number, and the second has 18.25. A struct generated from only the first record gets int64; the second record then fails at runtime.
Why it happens
- The sample was not representative. A single record, or a handful in which every value happened to be whole, produces an integer field for a quantity that is really a decimal.
- Prices and measurements in particular are often whole in test data and fractional in production.
- A percentage or a ratio that is usually
1or0but occasionally0.5. - A large integer that the producer serialised in exponent form (
1e6), which some encoders emit for round numbers and whichencoding/jsontreats as a float.
How to fix it
- Paste several records into the generator above, including one with a fractional value. It merges every item in the array, and it widens a field to
float64the moment any sample is fractional — that is precisely what a single-record sample cannot tell it. - Change the field in your existing struct to
float64. - If the value is money, consider the alternative: have the producer send integer minor units (
1825cents) and keepint64. Floating-point arithmetic on currency is its own class of bug. - If the number can be either an integer or a float and you need to know which, decode into
json.Numberand inspect the string.
The struct the merged sample produces:
type Root struct {
Total float64 `json:"total"`
}
If it still fails
- The same mismatch in Rust reads
invalid type: floating point \18.25`, expected i64, and in C#The JSON value could not be converted to System.Int32`. JSON to Rust and JSON to C# apply the same widening rule when given a fractional sample. - If the field is
intand the value is a whole number too large for it (9007199254740993and above on 32-bitint), the message is about range, not fractions; useint64. - A struct generated from documentation rather than data is the usual root cause. Generate from a real capture.
Related errors
json: cannot unmarshal string into Go struct field
Make the struct field match the payload (string), or fix the producer to send a number; for numbers-as-strings, tag the field with `json:",string"` or unmarshal into json.Number.
json: unknown field
Add the missing field to the struct (regenerate from a fuller sample), or stop calling DisallowUnknownFields if extra keys are acceptable; the default decoder ignores them.