What the error means
Go's encoding/json is strict about types. When it decodes a JSON value into a struct field, the JSON type and the Go type must be compatible: a JSON number into an int or float64, a JSON string into a string, a JSON bool into a bool. json: cannot unmarshal string into Go struct field User.id of type int means the payload carried a string for a field the struct declares as something else. The message names the struct, the field, and the Go type, which makes it one of the more helpful runtime errors.
In the example, id arrives as "42" and active as "true" — both strings. A struct generated from a sample where those were 42 and true will reject this payload, because the producer changed its mind about types.
Why it happens
- The API sends numbers as strings. Common with IDs (to avoid 64-bit precision loss in JavaScript clients), money amounts, and anything that passed through a form or a query string.
- The sample used to generate the struct had a different type than production data. One record with
"id": 42producesint; the real feed sends"42". - Booleans as
"true"/"false"strings, or"yes"/"no", from a legacy backend. - A nested object arriving as a JSON-encoded string — the classic double-encoding bug, where a field contains
"{\"a\":1}"instead of{"a":1}.
How to fix it
- Paste a representative payload into the generator above — the one that fails, not the one from the docs. It infers
stringfor any field whose sample value is a string, and the generated struct will decode the real data. - If the value is semantically a number and the producer will not change, keep the Go type and add the
stringoption to the tag:ID int64 \json:"id,string"`.encoding/jsonthen accepts"42"for that field and still rejects"forty-two"`. - For a field that may arrive as either type, decode into
json.Numberorjson.RawMessageand convert explicitly. - For a double-encoded object, unmarshal the outer document first, then unmarshal the string field's contents into the inner struct.
The struct that matches the example as sent:
type Root struct {
ID string `json:"id"`
Active string `json:"active"`
}
If it still fails
- Note which field the message names. If it is a nested struct field, the problem may be one level down:
cannot unmarshal string into Go struct field Order.customer of type main.Customermeanscustomerarrived as a string, not an object. - Validate the payload with JSON Validator to confirm the types you think are being sent are the types actually on the wire.
- The same payload against a TypeScript interface fails silently rather than loudly; JSON to TypeScript shows what a permissive typing of the same data looks like.
Related errors
json: cannot unmarshal number 18.25 into Go struct field Order.total of type int64
Change the field to float64 (the generator does this when any sample value is fractional), or keep integer cents in the payload if the value is money.
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.