我正在尝试从数据库中读取存储为字符串的JSON数据,我需要以不同的方式转换数据。我看到JSON.NET从JsonTextReader
内部抛出了一个错误。我试图通过直接使用以下代码重现错误。这段代码有什么问题?
var rs = new Newtonsoft.Json.JsonTextReader(new System.IO.StringReader("{'1':'2'}"));
rs.ReadAsString();
它会抛出错误:
解析值时遇到意外的字符:{。路径'',第1行,第1位。
答案 0 :(得分:2)
您收到错误是因为您错误地使用了JsonTextReader
。
JsonTextReader
类将JSON字符串视为一系列“标记”,一次读取一个“标记”。可能的令牌由JsonToken
枚举定义,包括StartObject
,StartArray
,PropertyName
,String
,Integer
,Boolean
,Null
,EndObject
和EndArray
仅举几例。
当您致电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(JObject)。例如:
var obj = JObject.Parse("{'1':'2'}");
foreach (JProperty prop in obj.Properties())
{
Console.WriteLine(prop.Name + ": " + prop.Value); // 1: 2
}