-
Notifications
You must be signed in to change notification settings - Fork 4.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Keep LineNumber, BytePositionInLine and Path when calling JsonSerializer.Deserialize<TValue>(ref reader) #77345
Comments
Tagging subscribers to this area: @dotnet/area-system-text-json, @gregsdennis Issue DetailsDescriptionA common pattern when implementing I'd like to keep the references Reproduction Stepsusing System.Text.Json;
using System.Text.Json.Serialization;
var json = @"{
""name"": ""test"",
""props"": [
""prop1"",
""prop2"",
[""this"", ""is"", ""a"", ""error""]
]
}";
try
{
var comp = JsonSerializer.Deserialize<MyComponent>(json, new JsonSerializerOptions(JsonSerializerDefaults.Web));
}
catch (JsonException e)
{
Console.WriteLine(e.Message);
Console.WriteLine($"Path: {e.Path}");
Console.WriteLine($"LineNumber: {e.LineNumber}");
Console.WriteLine($"BytePositionInLine: {e.BytePositionInLine}");
}
[JsonConverter(typeof(MyComponentConverter))]
public class MyComponent
{
public string? Name { get; set; }
public List<string>? Props { get; set; }
}
public class MyComponentConverter : JsonConverter<MyComponent>
{
public override MyComponent? Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options)
{
var component = new MyComponent();
while (reader.Read() && reader.TokenType != JsonTokenType.EndObject)
{
var propName = reader.GetString();
reader.Read();
switch (propName)
{
case "name":
component.Name = reader.GetString();
break;
case "props":
// use default behaviour for this list
component.Props = JsonSerializer.Deserialize<List<string>>(ref reader, options);
break;
default:
reader.Skip();
break;
}
}
return component;
}
public override void Write(Utf8JsonWriter writer, MyComponent value, JsonSerializerOptions options) => throw new NotImplementedException();
} Expected behaviorI expect the
Actual behaviorThe actual result resets the
Regression?I don't know, but assume this has always been this way. Known WorkaroundsI can read everything inside the custom converter from the Configurationdotnet 6 and 7 Other informationI have a draft solution that does not forward path information in main...ivarne:runtime:custom-recursive-json-parsing. Not sure if it is correct. I don't understand all the concepts here.
|
Thank you so much for triaging the issue. It's a duplicate of #67403. I'm sorry for not finding that one. I've looked at #63795, and don't really understand how the proposed solution will be required to fix this issue, nor that it will even help with this issue. At least when looking at the proposed solution, I think this is an orthogonal issue. This issue is about forwarding some of the internal state of the |
The error messages constructed in JsonSerializer exception reports are constructed based on state in the internal runtime/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs Line 259 in 33cb335
Until we expose the serialization state type (which is distinct from the JSON reader state in |
Yes, I saw that after my previous response, trying to update my suggestion to forward the |
Description
A common pattern when implementing
JsonConverter<MyType>
is to read a few properties and forward theUtf8JsonReader
toJsonSerializer.Deserialize<TValue>(ref reader)
to read some common type that don't need special handling. If aJsonException
is thrown in the forwarded call,LineNumber
,BytePositionInLine
andPath
is wrong with regards to the original json that was tried to deserialize.I'd like to keep the references
LineNumber
,BytePositionInLine
andPath
relative to the full json.Reproduction Steps
Expected behavior
I expect the
JsonException
to tell me where the parser was, when the error occurred. Just like it does when I don't use the custom converter.Actual behavior
The actual result resets the
e.Path
,e.LineNumber
ande.BytePositionInLine
when theUtf8JsonReader
is passed toJsonSerializer.Deserialize
Regression?
I don't know, but assume this has always been this way.
Known Workarounds
I can read everything inside the custom converter from the
Utf8JsonReader
without forwarding the simple components to the builtin tools.Configuration
dotnet 6 and 7
Other information
I have a draft solution that does not forward path information in main...ivarne:runtime:custom-recursive-json-parsing. Not sure if it is correct. I don't understand all the concepts here.
The text was updated successfully, but these errors were encountered: