使用 JsonTextReader 读取 JSON 会引发错误
Posted
技术标签:
【中文标题】使用 JsonTextReader 读取 JSON 会引发错误【英文标题】:Reading JSON using a JsonTextReader throws an error 【发布时间】:2017-10-12 10:58:19 【问题描述】:我正在尝试从数据库中读取存储为字符串的 JSON 数据,我需要以不同的方式转换数据。我看到 JSON.NET 在内部从 JsonTextReader
抛出错误。我试图通过直接使用以下代码来重现该错误。这段代码有什么问题?
var rs = new Newtonsoft.Json.JsonTextReader(new System.IO.StringReader("'1':'2'"));
rs.ReadAsString();
它会抛出一个错误:
解析值时遇到意外字符:。路径'',第 1 行,位置 1。
【问题讨论】:
【参考方案1】:您收到错误是因为您错误地使用了JsonTextReader
。
JsonTextReader
类将 JSON 字符串视为一系列“令牌”,一次读取一个。可能的令牌由JsonToken
枚举定义,包括StartObject
、StartArray
、PropertyName
、String
、Integer
、Boolean
、Null
、EndObject
和@987636@3 到4举几个例子。
当您调用ReadAsString
时,它会将阅读器推进到下一个标记并尝试将该标记解释为字符串。在您的 JSON 中,第一个标记不是字符串;它是StartObject
(对应于左大括号)。
ReadAsString
没有预料到这一点,所以它会抛出一个错误。
ReadAs...
方法仅在您已经预先知道阅读器遇到的下一个标记将是特定类型(例如字符串)的情况下才有用。如果事先不知道 JSON 结构,想用JsonTextReader
来扫描,可以循环调用Read
方法,直到返回false。每个Read
调用都会将阅读器推进到下一个令牌并设置TokenType
和Value
属性。然后您可以检查TokenType
以确定如何处理Value
。
这是一个简单的示例,它使用JsonTextReader
循环遍历 JSON 并在每个步骤中转储出 TokenType
和 Value
。这应该让您很好地了解读者如何看待您的 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 (JObjects)。例如:
var obj = JObject.Parse("'1':'2'");
foreach (JProperty prop in obj.Properties())
Console.WriteLine(prop.Name + ": " + prop.Value); // 1: 2
【讨论】:
谢谢。我已经想通了。我的意图是将完整的 JSON 作为字符串读取并反序列化。我必须为接口实现一个通用Task<T> Get<T>(key)
方法,其中实际实现需要从将数据存储为JSON 的数据存储中获取数据,主要是JSON 格式的序列化对象,但有时我也必须返回读取字符串,其中 T 是字符串,我为此使用了 JSONConvert.DeserilaizeObject<T>(string)
,这就是我得到这个错误的地方。以上是关于使用 JsonTextReader 读取 JSON 会引发错误的主要内容,如果未能解决你的问题,请参考以下文章
如何反序列化 JSONP 响应(最好使用 JsonTextReader 而不是字符串)?
如何反序列化 JSONP 响应(最好使用 JsonTextReader 而不是字符串)?