无法使用 Json.Net 反序列化 JSON 数组
Unable to deserialize a JSON array with Json.Net
我有一个 JSON 这样的:
[
{
"areas": [
{
"area": "New York",
"isDay": true,
"temp": "14"
},
{
"area": "Washington DC",
"isDay": true,
"temp": "30"
},
{
"area": "Los Angles",
"isDay": false,
"temp": "54"
},
{
"area": "San Diego",
"isDay": true,
"temp": "59"
}
],
"status": true,
"code": 200,
"created_at": "2019/06/18 22:26:34.475",
"request_time": "2019/06/18 22:25:28.306"
}
]
我正在尝试获取 Areas
数组下 first/second/third 对象的 area
值。
我试过这段代码来获取数组第一个区域的值,在本例中是“纽约”。
'Note that 'rawJSON' is a string variable that contains the JSON.
Dim jResults As JObject = JObject.Parse(rawJSON)
Dim naming As String = jResults("areas")("name")
然而,当我 运行 这个时,我得到异常:
Newtonsoft.Json.JsonReaderException: 'Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.'
我正在尝试编写一个函数,将每个数组中的所有 'areas' 及其标识符 area
(例如 New York/Washington DC)导入到 ListBox(因此 ListBox将依次包含:New York
、Washington DC
、Los Angles
).
我该怎么做?
这里有几个问题:
- 您的 JSON 以方括号开头和结尾,这意味着它是一个数组,而不是单个对象。因为它是一个数组,所以你需要使用
JArray.Parse()
来解析它而不是 JObject.Parse()
.
- 在您的数组中,有一个对象包含 属性
areas
以及一些其他属性,例如 status
和 code
。 areas
属性 的值也是一个数组,用方括号表示。因此,您的代码需要通过添加索引来考虑这两个数组。如果您想要第一项,则索引为零。
- 在您发布的 JSON 中没有任何 属性 被称为
name
。相反,每个城市的名称都在一个名为 area
. 的 属性 中
综上所述,如果你想从这个JSON中得到名字New York
,你会这样做:
Dim jResults As JArray = JArray.Parse(rawJSON)
Dim name As String = jResults(0)("areas")(0)("area")
演示:https://dotnetfiddle.net/eAfEsx
如果您要获取多个名称,则需要一个循环。你可以这样做:
Dim names As New List(Of String)()
For Each area As JObject In jResults(0)("areas")
Dim name As String = area("area")
names.Add(name)
Next
从您发布的JSON结构可以看出,JSON以方括号开头。那是数组的开始,StartArray
:当 JsonReader starts reading the JSON, the first TokenType
is a JsonToken.StartArray(错误告诉你的是什么)时。
然后是一个对象,由大括号定义:{ }
.
所以你有一个对象数组或列表。
此对象 (areas
) 的第一个 属性 是数组(或列表)类型。
它定义了对象的集合。
其他属性(status
、code
等)只有一个值。
[
{
"areas": [ { ... }, { ... } ]
"other": "other value"
}
]
你可以用JArray解析外层数组。数组中的第一个元素(也是您在此处显示的唯一一个元素)是外部数组。外层数组中第一个元素的第一个 属性 是 areas
数组。
所以你可以写:
Dim areasArray = JArray.Parse(rawJson)(0)("areas")
Dim firstAreaValue = areasArray(0)("area").ToString()
那么firstAreaValue
的值就是"New York"
.
这可能很烦人而且容易出错。您可以从 JSON 生成一个 class 模型,并使用此模型将 JSON 反序列化为 .Net classes,使其更易于处理,用作数据源、修改、序列化等
您的 JSON 是一个对象数组,所以让我们将根对象构建为 .Net class:
请注意,我已将 CreatedAt
和 RequestTime
属性的类型设置为 DateTime(日期):DateTime 的字符串格式 "2019/06/18 22:26:34.475"
可以正确反序列化。
DateTimeOffset
可能更好。您的选择。
Public Class AreasRoot
<JsonProperty("areas")>
Public Property Areas As List(Of AreaObject)
<JsonProperty("status")>
Public Property Status As Boolean
<JsonProperty("code")>
Public Property Code As Long
<JsonProperty("created_at")>
Public Property CreatedAt As DateTime
<JsonProperty("request_time")>
Public Property RequestTime As DateTime
End Class
区域 属性 是另一种对象类型的数组或列表,包含 3 个属性:
Public Class AreaObject
<JsonProperty("area")>
Public Property AreaArea As String
<JsonProperty("isDay")>
Public Property IsDay As Boolean
<JsonProperty("temp")>
Public Property Temp As Long
End Class
要使用此模型反序列化,请调用 JsonConvert.DeserializeObject(Of Type)(json)
。
如前所述,类型是数组或 List(Of RootObject)
:
Dim areasArray = JsonConvert.DeserializeObject(Of List(Of AreasRoot))(rawJson).First()
现在 New York
是:
Dim firstArea = areasArray.Areas.First().Area
' Or
Dim firstArea = areasArray.Areas(0).Area
您可以列出所有区域名称:
For Each areaObj In areasArray.Areas
Console.WriteLine(areaObj.Area)
Next
我有一个 JSON 这样的:
[
{
"areas": [
{
"area": "New York",
"isDay": true,
"temp": "14"
},
{
"area": "Washington DC",
"isDay": true,
"temp": "30"
},
{
"area": "Los Angles",
"isDay": false,
"temp": "54"
},
{
"area": "San Diego",
"isDay": true,
"temp": "59"
}
],
"status": true,
"code": 200,
"created_at": "2019/06/18 22:26:34.475",
"request_time": "2019/06/18 22:25:28.306"
}
]
我正在尝试获取 Areas
数组下 first/second/third 对象的 area
值。
我试过这段代码来获取数组第一个区域的值,在本例中是“纽约”。
'Note that 'rawJSON' is a string variable that contains the JSON.
Dim jResults As JObject = JObject.Parse(rawJSON)
Dim naming As String = jResults("areas")("name")
然而,当我 运行 这个时,我得到异常:
Newtonsoft.Json.JsonReaderException: 'Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.'
我正在尝试编写一个函数,将每个数组中的所有 'areas' 及其标识符 area
(例如 New York/Washington DC)导入到 ListBox(因此 ListBox将依次包含:New York
、Washington DC
、Los Angles
).
我该怎么做?
这里有几个问题:
- 您的 JSON 以方括号开头和结尾,这意味着它是一个数组,而不是单个对象。因为它是一个数组,所以你需要使用
JArray.Parse()
来解析它而不是JObject.Parse()
. - 在您的数组中,有一个对象包含 属性
areas
以及一些其他属性,例如status
和code
。areas
属性 的值也是一个数组,用方括号表示。因此,您的代码需要通过添加索引来考虑这两个数组。如果您想要第一项,则索引为零。 - 在您发布的 JSON 中没有任何 属性 被称为
name
。相反,每个城市的名称都在一个名为area
. 的 属性 中
综上所述,如果你想从这个JSON中得到名字New York
,你会这样做:
Dim jResults As JArray = JArray.Parse(rawJSON)
Dim name As String = jResults(0)("areas")(0)("area")
演示:https://dotnetfiddle.net/eAfEsx
如果您要获取多个名称,则需要一个循环。你可以这样做:
Dim names As New List(Of String)()
For Each area As JObject In jResults(0)("areas")
Dim name As String = area("area")
names.Add(name)
Next
从您发布的JSON结构可以看出,JSON以方括号开头。那是数组的开始,StartArray
:当 JsonReader starts reading the JSON, the first TokenType
is a JsonToken.StartArray(错误告诉你的是什么)时。
然后是一个对象,由大括号定义:{ }
.
所以你有一个对象数组或列表。
此对象 (areas
) 的第一个 属性 是数组(或列表)类型。
它定义了对象的集合。
其他属性(status
、code
等)只有一个值。
[
{
"areas": [ { ... }, { ... } ]
"other": "other value"
}
]
你可以用JArray解析外层数组。数组中的第一个元素(也是您在此处显示的唯一一个元素)是外部数组。外层数组中第一个元素的第一个 属性 是 areas
数组。
所以你可以写:
Dim areasArray = JArray.Parse(rawJson)(0)("areas")
Dim firstAreaValue = areasArray(0)("area").ToString()
那么firstAreaValue
的值就是"New York"
.
这可能很烦人而且容易出错。您可以从 JSON 生成一个 class 模型,并使用此模型将 JSON 反序列化为 .Net classes,使其更易于处理,用作数据源、修改、序列化等
您的 JSON 是一个对象数组,所以让我们将根对象构建为 .Net class:
请注意,我已将 CreatedAt
和 RequestTime
属性的类型设置为 DateTime(日期):DateTime 的字符串格式 "2019/06/18 22:26:34.475"
可以正确反序列化。
DateTimeOffset
可能更好。您的选择。
Public Class AreasRoot
<JsonProperty("areas")>
Public Property Areas As List(Of AreaObject)
<JsonProperty("status")>
Public Property Status As Boolean
<JsonProperty("code")>
Public Property Code As Long
<JsonProperty("created_at")>
Public Property CreatedAt As DateTime
<JsonProperty("request_time")>
Public Property RequestTime As DateTime
End Class
区域 属性 是另一种对象类型的数组或列表,包含 3 个属性:
Public Class AreaObject
<JsonProperty("area")>
Public Property AreaArea As String
<JsonProperty("isDay")>
Public Property IsDay As Boolean
<JsonProperty("temp")>
Public Property Temp As Long
End Class
要使用此模型反序列化,请调用 JsonConvert.DeserializeObject(Of Type)(json)
。
如前所述,类型是数组或 List(Of RootObject)
:
Dim areasArray = JsonConvert.DeserializeObject(Of List(Of AreasRoot))(rawJson).First()
现在 New York
是:
Dim firstArea = areasArray.Areas.First().Area
' Or
Dim firstArea = areasArray.Areas(0).Area
您可以列出所有区域名称:
For Each areaObj In areasArray.Areas
Console.WriteLine(areaObj.Area)
Next