How to Deserialize JSON with quoted numbers in C#
By FoxLearn Published on Mar 11, 2025 115
In this article, we will explore how quoted numbers are deserialized in Newtonsoft.Json
and System.Text.Json
, as well as how to adjust the behavior. Additionally, we’ll discuss how to serialize quoted numbers back into JSON.
Quoted Number Handling in Newtonsoft.Json
By default, Newtonsoft.Json handles both number literals and quoted numbers. When deserializing, it automatically converts quoted numbers to their appropriate target type.
Let's say we want to deserialize the following JSON with a product price:
{ "product": "Laptop", "price": "1999.99", "quantity": 50 }
Here’s how the code looks:
using Newtonsoft.Json; var productJson = "{ \"product\": \"Laptop\", \"price\": \"1999.99\", \"quantity\": 50 }"; var product = JsonConvert.DeserializeObject<Product>(productJson); Console.WriteLine($"Product={product.Product} Price={product.Price} Quantity={product.Quantity}");
This code outputs:
Product=Laptop Price=1999.99 Quantity=50
As you can see, Newtonsoft.Json was able to handle both the quoted price ("1999.99"
) and the numeric quantity (50
) without any issues.
Handling Quoted Decimal Values
If you're deserializing quoted decimal values that are formatted differently based on culture (e.g., using a comma as the decimal separator in Spain), Newtonsoft.Json will throw an error unless the appropriate culture is set.
Here's an example where the price is formatted in Spanish (e.g., "1.999,99"
):
{ "product": "Laptop", "price": "1.999,99", "quantity": 50 }
The solution is to specify the culture like so:
using Newtonsoft.Json; using System.Globalization; var productJson = "{ \"product\": \"Laptop\", \"price\": \"1.999,99\", \"quantity\": 50 }"; var product = JsonConvert.DeserializeObject<Product>(productJson, new JsonSerializerSettings() { Culture = CultureInfo.GetCultureInfo("es-ES") }); Console.WriteLine($"Product={product.Product} Price={product.Price} Quantity={product.Quantity}");
This would correctly parse the price as 1999.99
, outputting:
Product=Laptop Price=1999.99 Quantity=50
Quoted Number Handling in System.Text.Json
Unlike Newtonsoft.Json, System.Text.Json follows strict number handling by default. This means it only handles number literals (e.g., 123
). If it encounters quoted numbers, it throws an exception.
Let’s say we attempt to deserialize the following JSON with a quoted price:
{ "product": "Laptop", "price": "1999.99", "quantity": 50 }
With the default settings in System.Text.Json, we’ll get the following exception:
System.Text.Json.JsonException: The JSON value could not be converted to System.Decimal
Changing Quoted Number Handling in .NET 5 and Above
Starting in .NET 5, you can use the JsonNumberHandling.AllowReadingFromString
option to allow deserialization of quoted numbers.
Here’s how to adjust it:
using System.Text.Json; var jsonOptions = new JsonSerializerOptions() { NumberHandling = JsonNumberHandling.AllowReadingFromString }; var productJson = "{ \"product\": \"Laptop\", \"price\": \"1999.99\", \"quantity\": 50 }"; var product = JsonSerializer.Deserialize<Product>(productJson, jsonOptions); Console.WriteLine($"Product={product.Product} Price={product.Price} Quantity={product.Quantity}");
This would output:
Product=Laptop Price=1999.99 Quantity=50
Customizing Quoted Number Handling Per Property
You can apply JsonNumberHandling
to individual properties to customize behavior. For example, you may want to allow quoted numbers for the Price
property but use strict number handling for others:
using System.Text.Json.Serialization; class Product { public string Product { get; set; } [JsonNumberHandling(JsonNumberHandling.AllowReadingFromString)] public decimal Price { get; set; } public int Quantity { get; set; } }
Handling Quoted Decimal Values in Non-Default Formats
If your JSON contains quoted decimal values in a non-default format (like a comma separator in the Spanish format), System.Text.Json will not handle this directly. You'll need a custom converter.
For example:
Here’s a custom converter to handle quoted decimal values formatted according to the Spanish locale ("1.999,99"
):
using System.Text.Json; using System.Text.Json.Serialization; public class CultureSpecificDecimalConverter : JsonConverter<decimal> { public override decimal Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { return Convert.ToDecimal(reader.GetString(), System.Globalization.CultureInfo.GetCultureInfo("es-ES")); } return reader.GetDecimal(); } }
Now, you can use it like this:
var jsonOptions = new JsonSerializerOptions(); jsonOptions.Converters.Add(new CultureSpecificDecimalConverter()); var productJson = "{ \"product\": \"Laptop\", \"price\": \"1.999,99\", \"quantity\": 50 }"; var product = JsonSerializer.Deserialize<Product>(productJson, jsonOptions); Console.WriteLine($"Product={product.Product} Price={product.Price} Quantity={product.Quantity}");
This would correctly parse the price as 1999.99
, outputting:
Product=Laptop Price=1999.99 Quantity=50
Quoted Number Handling in ASP.NET Core
By default, ASP.NET Core uses System.Text.Json with JsonSerializerDefaults.Web
, which does not support quoted numbers unless changed in .NET 5 or later.
Before .NET 5, strict handling would result in 400 Bad Request errors for quoted numbers.
If you’re using .NET 5+, you can configure JsonNumberHandling.AllowReadingFromString
:
services.AddControllers().AddJsonOptions(options => { options.JsonSerializerOptions.NumberHandling = JsonNumberHandling.AllowReadingFromString; });
Writing Quoted Numbers During Serialization with System.Text.Json
If you want to serialize numbers as quoted strings, you can use JsonNumberHandling.WriteAsString
. For example:
var product = new Product() { Product = "Laptop", Price = 1999.99m, Quantity = 50 }; var jsonOptions = new JsonSerializerOptions() { NumberHandling = JsonNumberHandling.WriteAsString, WriteIndented = true }; var productJson = JsonSerializer.Serialize(product, jsonOptions); Console.WriteLine(productJson);
This outputs:
{ "Product": "Laptop", "Price": "1999.99", "Quantity": 50 }
Using Multiple NumberHandling Options
Since JsonNumberHandling
is an enum flag, you can combine multiple options with bitwise OR.
var jsonOptions = new JsonSerializerOptions() { NumberHandling = JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString };
You can also apply it to individual properties:
[JsonNumberHandling(JsonNumberHandling.WriteAsString | JsonNumberHandling.AllowReadingFromString)] public decimal Price { get; set; }
- Primitive types in C#
- How to set permissions for a directory in C#
- How to Convert Int to Byte Array in C#
- How to Convert string list to int list in C#
- How to convert timestamp to date in C#
- How to Get all files in a folder in C#
- How to use Channel as an async queue in C#
- Case sensitivity in JSON deserialization