Code Beautifier
json: cannot unmarshal number 18.25 into Go struct field Order.total of type int64

Fix "cannot unmarshal number 18.25 into Go struct field"

The JSON has a fractional number but the Go field is int64. Why a whole-number sample produced the wrong type, and how to widen it to float64.

Written by · Updated

Input that triggers it

[{"total": 18}, {"total": 18.25}]
Open JSON to Go on its own page
Options
json
Go structsgo
Draft saved locally.

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 1 or 0 but occasionally 0.5.
  • A large integer that the producer serialised in exponent form (1e6), which some encoders emit for round numbers and which encoding/json treats as a float.

How to fix it

  1. 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 float64 the moment any sample is fractional — that is precisely what a single-record sample cannot tell it.
  2. Change the field in your existing struct to float64.
  3. If the value is money, consider the alternative: have the producer send integer minor units (1825 cents) and keep int64. Floating-point arithmetic on currency is its own class of bug.
  4. If the number can be either an integer or a float and you need to know which, decode into json.Number and 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 int and the value is a whole number too large for it (9007199254740993 and above on 32-bit int), the message is about range, not fractions; use int64.
  • A struct generated from documentation rather than data is the usual root cause. Generate from a real capture.

Related errors