System.Json JsonValue ToString()和(string)强制转换

时间:2018-04-03 09:54:57

标签: c# .net

我想知道为什么ToString()和(string)之间存在值差异?

许多类似的问题都提到,唯一的区别应该是您无法在ToString()值上调用null

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)

4 个答案:

答案 0 :(得分:3)

方法System.Json.JsonObject.Parse会返回JsonValue个对象,查看此处提供的源代码:https://github.com/dotnet/corefx/blob/master/src/System.Json/src/System/Json/JsonValue.cs

我们可以看到方法ToString()实现如下:

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);
    }
}

但是,为了支持使用(string)转换为字符串,该类实现以下内容:

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

通过查看此处提供的JsonPrimitive的实施方式:https://github.com/dotnet/corefx/blob/master/src/System.Json/src/System/Json/JsonPrimitive.cs

我们可以看到有一种方法可以格式化字符串,如下所示:

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();
    }
}

这就是你得到不同结果的原因。

答案 1 :(得分:2)

原因是System.Json.JsonObject继承自System.Json.JsonValue,该类会使用自己的实现覆盖Object.ToString()

  

ToString - 将此JSON CLR类型保存(序列化)为基于文本的JSON。 (重写Object.ToString()。)

来源:https://docs.microsoft.com/en-us/previous-versions/windows/silverlight/dotnet-windows-silverlight/cc626526(v%3dvs.95)

要将字符串正确序列化为JSON,需要引号。

答案 2 :(得分:2)

Assert失败的原因是JsonValue.ToString()方法是一个覆盖,返回 基于文本的JSON字符串 结果,而直接转换值则返回基础字符串值。

var test = new JsonPrimitive("test");
Console.WriteLine((string)test);    // test
Console.WriteLine(test.ToString()); // "test" - with quotes

答案 3 :(得分:1)

根据此documentation ToString方法:

  

将此JSON CLR类型保存(序列化)为基于文本的JSON。

所以它覆盖了Object.ToString()的行为。