Description
We are in the process of migrating from Newtonsoft.Json
to System.Text.Json
following similar steps as described here.
Unfortunately System.Text.Json
exception messages are of lower quality than the corresponding exception messages produced by Newtonsoft.Json
. In our ASP.NET Core application this gets exacerbated for the validation errors and the end result is an API which is less user friendly. Please see this issue for more details.
In the following examples we try to deserialize a JSON string to this class:
public class Model
{
public Guid Id { get; set; }
public int Integer { get; set; }
public string String { get; set; }
}
For the different jsonString
values listed below, this code was executed:
try
{
Model model = Newtonsoft.Json.JsonConvert.DeserializeObject<Model>(jsonString);
}
catch (Newtonsoft.Json.JsonException oldEx)
{
// The value of oldEx.Message will be listed below.
}
try
{
Model model = System.Text.Json.JsonSerializer.Deserialize<Model>(jsonString);
}
catch (System.Text.Json.JsonException newEx)
{
// The value of newEx will be listed below.
}
Example 1:
string jsonString =
@"{
""Id"": ""00000000-0000-0000-0000-00000000000x""
}";
=>
oldEx: "Error converting value \"00000000-0000-0000-0000-00000000000x\" to type 'System.Guid'. Path 'Id', line 2, position 64."
newEx: "The JSON value could not be converted to System.Guid. Path: $.Id | LineNumber: 1 | BytePositionInLine: 64."
Example 2:
string jsonString =
@"{
""Integer"": 2x
}";
=>
oldEx: "Input string '2x' is not a valid integer. Path 'Integer', line 2, position 33."
newEx: "'x' is an invalid end of a number. Expected a delimiter. Path: $.Integer | LineNumber: 1 | BytePositionInLine: 32."
Example 3:
string jsonString =
@"{
""string"": 2 x
}";
=>
oldEx: "After parsing a value an unexpected character was encountered: x. Path 'string', line 2, position 32."
newEx: "'x' is invalid after a value. Expected either ',', '}', or ']'. Path: $ | LineNumber: 1 | BytePositionInLine: 32."
All of these error messages are now harder to understand. In addition, the paths are less helpful and humans do not start counting line numbers from zero. It would be great if System.Text
could produce exception error messages that were of the same quality as Newtonsoft.Json
.
Also, with this JSON string:
string jsonString =
@"{
""string"": 2
}";
then there is no exception thrown for neither Newtonsoft.Json
nor System.Text.Json
, but the deserialized values differ: model.string
is "2"
for Newtonsoft.Json
(this kind of leniency and the lack of a strict mode in Newtonsoft.Json
is one the reasons we wanted to migrate in the first place). However, System.Text.Json
leaves model.string
as null
, which is odd (I would have expected an exception here). In the ASP.NET Core application this case results in a validation error when using System.Text.Json
.