What the error means
System.Text.Json is strict about numeric conversion. JsonException: The JSON value could not be converted to System.Int32. Path: $.id | LineNumber: 0 | BytePositionInLine: 10 means the value at that path could not be read as a 32-bit integer. The Path is the useful part: $.id points straight at the property. The same message appears with System.Int64, System.Boolean, and other primitives.
The example triggers it three ways: "id" is a string, total has a fractional part, and rank is null in a non-nullable property.
Why it happens
- A quoted number.
"42"is a string;System.Text.Jsondoes not read it intointunless told to. Newtonsoft.Json does, which is why migrating from Newtonsoft surfaces this. - A fractional value for an integer property.
18.25cannot be anint; it needsdecimalordouble. - Null for a non-nullable value type.
intcannot hold null;int?can. - The class was generated from an unrepresentative sample, so the property types reflect the sample rather than the data.
How to fix it
- Paste a representative payload into the generator above. It emits
longfor integers (a safer default thanintfor IDs and counters),doublefor any field with a fractional sample,stringfor quoted values, andlong?for a field that is ever null. - In an existing class, change the property type to match the data at the reported path.
- For quoted numbers you would rather coerce than retype, enable it on the options:
new JsonSerializerOptions { NumberHandling = JsonNumberHandling.AllowReadingFromString }, or annotate the property with[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]. - For null, make the property nullable (
long?) rather than suppressing the error.
The class the example produces:
public class Root
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("total")]
public double Total { get; set; }
[JsonPropertyName("rank")]
public long? Rank { get; set; }
}
If it still fails
- Read the
Pathin the exception.$.items[3].pricemeans the third element ofitems, not the top-level object; the fix goes on the element's class. - Jackson's equivalent for the quoted-number case is
InvalidFormatException: Cannot deserialize value of type \long` from String`; JSON to Java covers the same decision. - If the value is an identifier rather than a quantity,
stringis the honest type — JSON to TypeScript will show it the same way.
Related errors
CS8618: Non-nullable property must contain a non-null value when exiting constructor
Mark the property required (C# 11+), give it a default such as string.Empty, or make it nullable (string?) when the JSON can genuinely omit it.
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.