【问题标题】:Reading JSON using a JsonTextReader throws an error使用 JsonTextReader 读取 JSON 会引发错误
【发布时间】: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。

【问题讨论】:

    标签: c# json json.net


    【解决方案1】:

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

    JsonTextReader 类将 JSON 字符串视为一系列“令牌”,一次读取一个。可能的令牌由JsonToken 枚举定义,包括StartObjectStartArrayPropertyNameStringIntegerBooleanNullEndObject 和@987636@3 到4举几个例子。

    当您调用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 (JObjects)。例如:

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

    【讨论】:

    • 谢谢。我已经想通了。我的意图是将完整的 JSON 作为字符串读取并反序列化。我必须为接口实现一个通用Task&lt;T&gt; Get&lt;T&gt;(key) 方法,其中实际实现需要从将数据存储为JSON 的数据存储中获取数据,主要是JSON 格式的序列化对象,但有时我也必须返回读取字符串,其中 T 是字符串,我为此使用了 JSONConvert.DeserilaizeObject&lt;T&gt;(string),这就是我得到这个错误的地方。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多