Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

System.Json JsonValue ToString() and (string) cast difference

Tags:

c#

.net

I'm wondering why there is a difference of values between ToString() and (string) cast?

Many similar questions are referring that only difference should be that you can't call ToString() on null value.

var json = "{\"someKey\":\"Hello world!\"}";
var jsonObject = System.Json.JsonObject.Parse(json);

Assert.AreEqual("Hello world!", (string)jsonObject["someKey"]);    //ok 
Assert.AreEqual("Hello world!", jsonObject["someKey"].ToString()); //not equal, actual value is "Hello world!" (with quotes in the string)
like image 618
Vojtěch Sázel Avatar asked Oct 25 '25 23:10

Vojtěch Sázel


2 Answers

The reason your Assert is failing is because the JsonValue.ToString() method is an override that returns a text based JSON string result whereas casting the value directly returns the underlying string value.

var test = new JsonPrimitive("test");
Console.WriteLine((string)test);    // test
Console.WriteLine(test.ToString()); // "test" - with quotes
like image 77
Chris Pickford Avatar answered Oct 27 '25 11:10

Chris Pickford


The method System.Json.JsonObject.Parse returns a JsonValue object, looking at the source code available here: https://github.com/dotnet/corefx/blob/master/src/System.Json/src/System/Json/JsonValue.cs

We can see that the method ToString() is implemented as follows:

public override string ToString()
{
    var sw = new StringWriter();
    Save(sw);
    return sw.ToString();
}

public virtual void Save(Stream stream)
{
    if (stream == null)
    {
        throw new ArgumentNullException(nameof(stream));
    }

    using (StreamWriter writer = new StreamWriter(stream, s_encoding, 1024, true))
    {
        Save(writer);
    }
}

However, to support casting to string using (string) that class implements the following:

 public static implicit operator JsonValue(string value) => new JsonPrimitive(value);

And by looking at the implementation of JsonPrimitive available here: https://github.com/dotnet/corefx/blob/master/src/System.Json/src/System/Json/JsonPrimitive.cs

We can see there is a method that will format the string as follows:

internal string GetFormattedString()
{
    switch (JsonType)
    {
        case JsonType.String:
            if (_value is string || _value == null)
            {
                return (string)_value;
            }
            if (_value is char)
            {
                return _value.ToString();
            }
            throw new NotImplementedException(SR.Format(SR.NotImplemented_GetFormattedString, _value.GetType()));

        case JsonType.Number:
            string s = _value is float || _value is double ?
                ((IFormattable)_value).ToString("R", NumberFormatInfo.InvariantInfo) : // Use "round-trip" format
                ((IFormattable)_value).ToString("G", NumberFormatInfo.InvariantInfo);
            return s == "NaN" || s == "Infinity" || s == "-Infinity" ?
                "\"" + s + "\"" :
                s;

        default:
            throw new InvalidOperationException();
    }
}

That's the reason you are getting different results.

like image 26
Isma Avatar answered Oct 27 '25 13:10

Isma



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!