Updated October 2026 for .NET 10 (LTS) and System.Text.Json 10.

System.Text.Json could not turn a JSON value into an int. The usual reasons are a number sent as a string ("42"), an empty string, a decimal, a value too large for int, or null. The fix depends on which one you have, and the Path in the message tells you where to look.

The error

System.Text.Json.JsonException: The JSON value could not be converted to System.Int32. Path: $.Address.ZipCode | LineNumber: 5 | BytePositionInLine: 23.
 ---> System.InvalidOperationException: Cannot get the value of a token type 'String' as a number.

Find your cause

JSON valueCauseFix
"42"Number sent as a stringFix 1
"" or "N/A"Empty or non-numeric textFix 2
nullMissing value, but int cannot be nullUse int?
12.5Decimal into a whole-number typeUse decimal or double
3000000000Too large for intUse long

Fix 1: Allow numbers in quotes

This JSON sends ZipCode as a string:

{
  "FirstName": "Ann",
  "EmployeeId": 1042,
  "Address": {
    "ZipCode": "30301",
    "State": "GA"
  }
}

Tell the serializer to accept quoted numbers. The simplest way is the web defaults, which ASP.NET Core already uses for request bodies:

using System.Text.Json;
using System.Text.Json.Serialization;

// Option A: web defaults (camelCase names + numbers in quotes)
var options = new JsonSerializerOptions(JsonSerializerDefaults.Web);

// Option B: only allow numbers in quotes
var strictOptions = new JsonSerializerOptions
{
    NumberHandling = JsonNumberHandling.AllowReadingFromString
};

var customer = JsonSerializer.Deserialize<Customer>(json, options);

public class Customer
{
    public string FirstName { get; set; } = "";
    public int EmployeeId { get; set; }
    public Address Address { get; set; } = new();
}

public class Address
{
    public int ZipCode { get; set; }
    public string State { get; set; } = "";
}

To allow it for one property only, use an attribute:

[JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)]
public int ZipCode { get; set; }

Getting this error in an ASP.NET Core API? Request bodies already accept quoted numbers, so the value is probably empty, non-numeric or null. Go to Fix 2. If you created your own JsonSerializerOptions with new(), you lost the web defaults; use new(JsonSerializerDefaults.Web) instead.

Fix 2: Empty strings, “N/A” and null

Quoted-number handling does not help with "" or text like "N/A". If those really mean “no value”, make the property nullable and add a converter that maps them to null:

using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

public sealed class LenientNullableIntConverter : JsonConverter<int?>
{
    public override int? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        switch (reader.TokenType)
        {
            case JsonTokenType.Null:
                return null;
            case JsonTokenType.Number:
                return reader.GetInt32();
            case JsonTokenType.String:
                var text = reader.GetString();
                if (string.IsNullOrWhiteSpace(text) || text == "N/A") return null;
                if (int.TryParse(text, NumberStyles.Integer, CultureInfo.InvariantCulture, out var value)) return value;
                throw new JsonException($"'{text}' is not a valid whole number.");
            default:
                throw new JsonException($"Unexpected token {reader.TokenType} for an integer.");
        }
    }

    public override void Write(Utf8JsonWriter writer, int? value, JsonSerializerOptions options)
    {
        if (value is null) writer.WriteNullValue();
        else writer.WriteNumberValue(value.Value);
    }
}
public class Address
{
    [JsonConverter(typeof(LenientNullableIntConverter))]
    public int? ZipCode { get; set; }
    public string State { get; set; } = "";
}

If null is the only problem, changing int to int? is enough. No converter is needed.

Fix 3: Use the right number type

  • Prices and amounts such as 49.99: use decimal.
  • Large ids such as 3000000000: use long. int stops at 2,147,483,647.
  • Codes that can start with zero, such as "02139": keep them as string. As a number, the leading zero is lost.

To get suitable types for your JSON automatically, paste a sample into the free C# Class Converter.

FAQ

Why did Newtonsoft.Json accept this?

Newtonsoft converts strings to numbers automatically. System.Text.Json only does this when you allow it, as shown in Fix 1. If you need Newtonsoft’s behaviour for a whole API, see Add Newtonsoft.Json support in ASP.NET Core.

Can I write numbers back as strings?

Yes. Add JsonNumberHandling.WriteAsString, for example AllowReadingFromString | WriteAsString.

Related

Sources: Microsoft Learn: Allow some kinds of invalid JSON · Microsoft Learn: Write custom converters