无法使用 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 YorkWashington DCLos Angles).

我该怎么做?

这里有几个问题:

  1. 您的 JSON 以方括号开头和结尾,这意味着它是一个数组,而不是单个对象。因为它是一个数组,所以你需要使用 JArray.Parse() 来解析它而不是 JObject.Parse().
  2. 在您的数组中,有一个对象包含 属性 areas 以及一些其他属性,例如 statuscodeareas 属性 的值也是一个数组,用方括号表示。因此,您的代码需要通过添加索引来考虑这两个数组。如果您想要第一项,则索引为零。
  3. 在您发布的 JSON 中没有任何 属性 被称为 name。相反,每个城市的名称都在一个名为 area.
  4. 的 属性 中

综上所述,如果你想从这个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

演示:https://dotnetfiddle.net/BtSa6O

从您发布的JSON结构可以看出,JSON以方括号开头。那是数组的开始,StartArray:当 JsonReader starts reading the JSON, the first TokenType is a JsonToken.StartArray(错误告诉你的是什么)时。
然后是一个对象,由大括号定义:{ }.
所以你有一个对象数组或列表。

此对象 (areas) 的第一个 属性 是数组(或列表)类型。
它定义了对象的集合。
其他属性(statuscode 等)只有一个值。

[
  {
      "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:
请注意,我已将 CreatedAtRequestTime 属性的类型设置为 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