Skip to content
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

JsonReader.ReadAsString() doesn't return the contents of JsonToken.Raw tokens #2876

Open
mlorbetske opened this issue Jul 17, 2023 · 3 comments

Comments

@mlorbetske
Copy link

mlorbetske commented Jul 17, 2023

Source/destination types and Repro Steps

[JsonConverter(typeof(DecimalLikeConverter))]
public class DecimalLikeThing
{
    public decimal D { get; set; }
}

public class DecimalLikeConverter : JsonConverter
{
    public override bool CanConvert(Type objectType) => true;

    public override object? ReadJson(JsonReader reader, Type objectType, object? existingValue, JsonSerializer serializer)
    {
        reader.Read();
        var value = reader.ReadAsString();
        var result = new DecimalLikeThing
        {
            D = decimal.Parse(value ?? "0"),
        };

        reader.Read();
        return result;
    }
    
    public override void WriteJson(JsonWriter writer, object? value, JsonSerializer serializer)
    {
        var x = (DecimalLikeThing)value!;
        writer.WriteStartObject();
        writer.WritePropertyName("D");
        writer.WriteRawValue(x.D.ToString());
        writer.WriteEndObject();
    }
}

public void Run()
{
    var x = new DecimalLikeThing
    {
       D = 100.300M,
    };

    var res = JToken.FromObject(x);
    res.ToObject<DecimalLikeThing>(); //<-- This throws the exception noted below

    var text = res.ToString(Formatting.None);
    var text = res.ToString(Formatting.None);
    var f = JsonConvert.DeserializeObject(text, typeof(DecimalLikeThing)); // <-- This succeeds because the JToken doesn't contain a token noted to by of type Raw
}

Source/destination JSON

{
  "D": 100.300
}

Expected behavior

The ReadAsString() call in the JsonConverter above should have returned the text captured in the Raw type token

Actual behavior

Newtonsoft.Json.JsonReaderException: 'Error reading string. Unexpected token: Raw. Path 'D'.'
at Newtonsoft.Json.JsonReader.ReadAsString() in /_/Src/Newtonsoft.Json/JsonReader.cs:line 507

@mlorbetske
Copy link
Author

PR available in #2877

mlorbetske added a commit to mlorbetske/Newtonsoft.Json that referenced this issue Jul 17, 2023
…returned when calling JsonReader.ReadAsString()
@elgonzo
Copy link

elgonzo commented Jul 18, 2023

It's debatable whether this is a bug requiring a fix or whether this is intentional behavior, and since i am not the author nor a maintainer of Newtonsoft.Json i leave it to them to evaluate this situation.

However, as a side note and unrelated to the issue your report is about, please note that doing writer.WriteRawValue(x.D.ToString()); in your WriteJson method is wrong, as it can lead to invalid json. Transforming the decimal to a string using the parameterless ToString() method uses the current culture. If the current culture uses a decimal comma, writing x.D.ToString() as raw value will screw up the resulting json.

@mlorbetske
Copy link
Author

@elgonzo thanks for the response. yep, the converter was just an example, not intended to be production-ready code.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants