【问题标题】:Unable to deserialize a JSON array with Json.Net无法使用 Json.Net 反序列化 JSON 数组
【发布时间】:2026-02-05 05:10:01
【问题描述】:

我有一个这样的 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 数组下第一个/第二个/第三个对象上的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: '从 JsonReader 读取 JObject 时出错。当前 JsonReader 项不是对象:StartArray。路径'',第 1 行,位置 1。'

我正在尝试编写一个函数,将每个数组中的所有“区域”及其标识符为 area(例如纽约/华盛顿特区)导入 ListBox(因此 ListBox 将按顺序包含:@987654326 @、Washington DCLos Angles)。

我该怎么做?

【问题讨论】:

  • psuedocode jResults[0].("areas").[0].("name") 最外面的对象是一个数组。

标签: json .net vb.net json.net


【解决方案1】:

这里有几个问题:

  1. 您的 JSON 以方括号开头和结尾,这意味着它是一个数组,而不是单个对象。由于它是一个数组,您需要使用JArray.Parse() 来解析它,而不是使用JObject.Parse()
  2. 在您的数组中,有一个对象包含属性areas 以及一些其他属性,例如statuscodeareas 属性的值也是一个数组,用方括号表示。因此,您的代码需要通过添加索引来考虑这两个数组。如果您想要第一项,那就是索引为零。
  3. 在您发布的 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

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

【讨论】:

    【解决方案2】:

    从您发布的 JSON 结构中可以看出,JSON 以方括号开头。那是数组的开头,StartArray:当JsonReader 开始读取 JSON 时,第一个 TokenTypeJsonToken.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 生成类模型,并使用此模型将 JSON 反序列化为 .Net 类,使其更易于处理、用作数据源、修改、序列化等。

    您的 JSON 是一个对象数组,因此让我们将根对象构建为 .Net 类:
    请注意,我已将CreatedAtRequestTime 属性的Type 设置为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
    

    Areas 属性是另一种类型对象的数组或列表,包含 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
    

    【讨论】:

      最近更新 更多