使用JsonTextReader读取JSON会引发错误

时间:2017-10-12 10:58:19

标签: c# json json.net

我正在尝试从数据库中读取存储为字符串的JSON数据,我需要以不同的方式转换数据。我看到JSON.NET从JsonTextReader内部抛出了一个错误。我试图通过直接使用以下代码重现错误。这段代码有什么问题?

var rs = new Newtonsoft.Json.JsonTextReader(new System.IO.StringReader("{'1':'2'}"));
rs.ReadAsString();

它会抛出错误:

  

解析值时遇到意外的字符:{。路径'',第1行,第1位。

1 个答案:

答案 0 :(得分:2)

您收到错误是因为您错误地使用了JsonTextReader

JsonTextReader类将JSON字符串视为一系列“标记”,一次读取一个“标记”。可能的令牌由JsonToken枚举定义,包括StartObjectStartArrayPropertyNameStringIntegerBooleanNullEndObjectEndArray仅举几例。

当您致电ReadAsString时,会使读者前进到下一个令牌并尝试将该令牌解释为字符串。在您的JSON中,第一个标记不是字符串;它是StartObject(对应于左大括号{)。 ReadAsString并不期望这样,所以它会引发错误。

ReadAs...方法实际上仅在您事先已知道读者遇到的下一个标记是特定类型(例如字符串)的情况下才有用。如果您事先不知道JSON结构并希望使用JsonTextReader来扫描它,则可以通过在循环中调用Read方法来执行此操作,直到它返回false。每次Read调用都会使读者前进到下一个令牌并设置TokenTypeValue属性。然后,您可以查看TokenType以确定如何处理Value

这是一个简单的示例,它使用JsonTextReader遍历JSON并在每一步中转储TokenTypeValue。这应该可以让您了解读者如何看待您的JSON:

JsonTextReader rs = new JsonTextReader(new StringReader("{'1':'2'}"));

Console.WriteLine("TokenType     Value");
Console.WriteLine("------------  ------");
while (rs.Read())
{
    Console.WriteLine(string.Format("{0,-12}  {1}", 
        rs.TokenType.ToString(),
        rs.Value != null ? rs.Value.ToString() : "(null)"));
}

小提琴:https://dotnetfiddle.net/nxWd1X

这是输出:

TokenType     Value
------------  ------
StartObject   (null)
PropertyName  1
String        2
EndObject     (null)

请记住,JsonTextReader是用于解析JSON的相当低级的API,并且除了最简单的JSON结构之外,它可能变得难以使用。如果您的JSON具有众所周知的结构,则可能更容易定义匹配的类(或类集)并使用JsonConvert.DeserializeObject<T>反序列化为该类。例如:

public class RootObject
{
    [JsonProperty("1")]
    public string One { get; set; }
}

var root = JsonConvert.DeserializeObject<RootObject>("{'1':'2'}");

Console.WriteLine(root.One);   // 2

或者,如果您的JSON结构是动态的或不为人所知,则可以使用LINQ-to-JSON API(JObject)。例如:

var obj = JObject.Parse("{'1':'2'}");
foreach (JProperty prop in obj.Properties())
{
    Console.WriteLine(prop.Name + ": " + prop.Value);   // 1: 2
}