When I send a request to the endpoint with an escaped JSON string it throws an exception "JSON value could not be converted to Test.TestClass . Path: $ | LineNumber: 0 | BytePositionInLine: 90.\r\n"". How can I enable escaped JSON string parsing in ASP.NET 5? I am using System.Text.Json (v 6.0.1). Tried updating to (v8) but no luck. Also tried using AddNewtonsoftJson() but still got the same result.
Creating a custom JSON converter works but need a solution which applies globally.
The curl for my request with the escaped JSON string.
curl --location 'https://localhost:8080/api/testEndpoint' \
--header 'charset: utf-8' \
--header 'Content-Type: application/json' \
--data '"{\"testId\":0,\"created\":\"2024-03-09T14:17:19.9837955Z\"}"'
The model class
public class TestClass
{
public int TestId {get;set;}
public DateTime Created {get;set;}
}
The issue was the client was double serializing the the request JSON. Thanks @Panagiotis Kanavos for pointing out.
However, until the client side issue is resolved I created a custom JSON converter to temporarily handle the issue. And posting it since it could be useful to anyone else for a different purpose.
In the below code just implement a blank interface 'IJSONStringDto' to the endpoint dtos and the converter will handle the normal JSON parsing and double serialized JSON parsing.
public class JSONStringConverterFactory : JsonConverterFactory
{
public override bool CanConvert(Type typeToConvert)
{
if (typeof(IJSONStringDto).IsAssignableFrom(typeToConvert))
{
return true;
}
return false;
}
public override JsonConverter CreateConverter(Type typeToConvert, JsonSerializerOptions options)
{
JsonConverter converter = (JsonConverter)Activator.CreateInstance(
typeof(JSONStringObjectConverter<>).MakeGenericType(
new Type[] { typeToConvert }),
BindingFlags.Instance | BindingFlags.Public,
binder: null,
args: new object[] { options },
culture: null);
return converter;
}
private class JSONStringObjectConverter<TJSONStringType> : JsonConverter<TJSONStringType> where TJSONStringType: IJSONStringDto
{
public JSONStringObjectConverter(JsonSerializerOptions options)
{
}
public override TJSONStringType? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
if (reader.TokenType == JsonTokenType.String)
{
return JsonSerializer.Deserialize<TJSONStringType>(reader.GetString());
}
using (var jsonDoc = JsonDocument.ParseValue(ref reader))
{
return JsonSerializer.Deserialize<TJSONStringType>(jsonDoc.RootElement.GetRawText());
}
}
public override void Write(Utf8JsonWriter writer, TJSONStringType value, JsonSerializerOptions options)
{
throw new NotImplementedException();
}
}
}
Then register the converter
.AddJsonOptions(options =>
{
options.JsonSerializerOptions.Converters.Add(new JSONStringConverterFactory());
});