JSON value could not be converted to System.String in C#

By FoxLearn 3/13/2025 2:50:08 AM   33
When you send a request to an ASP.NET API with a JSON body, you might encounter the following exception:
System.Text.Json.JsonException: The JSON value could not be converted to System.Int32. Path: $.Age | LineNumber: 0 | BytePositionInLine: 1.

This error occurs when the framework tries to deserialize a JSON value into an integer (System.Int32), but the actual value might not match the expected type. You might be using an integer parameter with [FromBody], or the model you are binding has an integer property that maps to a nested JSON object.

To solve this, you have two options:

  1. Use JsonElement for flexible type handling.
  2. Manually deserialize the request body to the correct type.

I'll walk you through examples for both solutions below.

Option 1 - Use JsonElement Instead of int

Instead of binding the JSON value directly to an integer property, you can use JsonElement. This allows you to inspect the raw JSON content and process it more flexibly.

using System.Text.Json;

[HttpPost()]
public IActionResult Post([FromBody] JsonElement jsonElement)
{
    // Access a specific property
    _logger.LogInformation($"Age={jsonElement.GetProperty("Age")}");

    return Ok();
}

In this example, the JsonElement lets you check properties, and you can also manually convert them into the right type if necessary. For instance:

if (jsonElement.TryGetProperty("Age", out JsonElement ageElement) 
    && ageElement.ValueKind == JsonValueKind.Number)
{
    int age = ageElement.GetInt32();
}

Here, JsonElement gives you the flexibility to handle different kinds of data without directly binding to a specific type.

Option 2 - Manually Deserialize the JSON Request Body

If you need to handle a dynamic request body, especially when the type is determined at runtime (e.g., based on a header), you can manually deserialize the request body. This method is useful if you have a "type discriminator" in the request to decide the correct model.

using System.Text.Json;

[HttpPost()]
public async Task<IActionResult> Post([FromHeader] string type)
{
    if (type == "User")
    {
        User user = await JsonSerializer.DeserializeAsync<User>(Request.Body);
        _logger.LogInformation($"Received user with name: {user.Name}");
    }

    return Ok();
}

In this case, you’re using DeserializeAsync() to asynchronously read the request body and convert it to the appropriate type based on the value of the type header. Note that DeserializeAsync() is necessary because you can’t perform synchronous I/O operations by default.

This approach allows you to handle requests with dynamic or varying structures, especially when the type of the content isn't known until runtime.