【问题标题】:How to extract a specific object from a JSON?如何从 JSON 中提取特定对象?
【发布时间】:2021-01-06 12:26:57
【问题描述】:

我想知道如何从 JSON 中提取特定对象。
在发布此之前,我在 Stackoverflow 上看到了大部分问题已解决,但没有人已经谈论过这个。

我想从 JSON 对象中获取 slug 值。
这是我的代码Get Users From JSON

Imports System
Imports Newtonsoft.Json.Linq
                
Public Module Module1
    Public Sub Main()
        Dim myJsonString = New System.IO.StreamReader(New System.Net.WebClient().
            OpenRead("https://pastebin.com/raw/z4GZFuF3")).ReadToEnd()
        
        Dim myJObject = JObject.Parse(myJsonString)
        For Each match In myJObject("matches")
        Console.WriteLine(match("id")("slug"))
        Next
    End Sub
End Module

这是输出:

Run-time exception (line -1): Error reading JObject from JsonReader.  
Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.

Stack Trace:

[Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader.  
   Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.]
   at Newtonsoft.Json.Linq.JObject.Load(JsonReader reader, JsonLoadSettings settings)
   at Newtonsoft.Json.Linq.JObject.Parse(String json, JsonLoadSettings settings)
   at Newtonsoft.Json.Linq.JObject.Parse(String json)
   at Module1.Main()

由于此错误,我减少的是 JSON 文本中不存在对象 "matches",但我不知道我应该在其位置指定什么才能使其正常工作。

【问题讨论】:

  • 该链接中 JSON 的根是 JArray,而不是 JObject,并且没有 matches 对象。我建议将此 JSON 作为 .Net 类进行解析和处理。
  • 你好 Jimi,谢谢你的回复,你能给我一个例子吗?因为你已经知道我不太了解开发我是初学者,提前谢谢你。
  • 在你向我解释问题后我找到了这个例子,这对我有帮助吗? How To Parse JSON In .NET Core

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


【解决方案1】:

可以从提供的地址检索到的JSON:
(http://www.stginternational.org/wp-json/wp/v2/users)
是一个对象数组。
可以使用JArray.Parse() 对其进行解析,但我建议将此 JSON 反序列化为 .Net 类:它更容易处理。

JSON 的基础对象(数组中的每个对象)定义如下:

{
  "id": 1,
  "name": "drall",
  "url": "",
  "description": "",
  "link": "http://www.stginternational.org/author/drall/",
  "slug": "drall",
  "avatar_urls": {
    "24": "http://1.gravatar.com/avatar/dc6dd0ef71784957b629e124f19364cb?s=24&d=mm&r=g",
    "48": "http://1.gravatar.com/avatar/dc6dd0ef71784957b629e124f19364cb?s=48&d=mm&r=g",
    "96": "http://1.gravatar.com/avatar/dc6dd0ef71784957b629e124f19364cb?s=96&d=mm&r=g"
  },
  "meta": [],
  "_links": {
    "self": [
      {
        "href": "http://www.stginternational.org/wp-json/wp/v2/users/1"
      }
    ],
    "collection": [
      {
        "href": "http://www.stginternational.org/wp-json/wp/v2/users"
      }
    ]
  }
}

它可以由这些 .Net 类表示:

Public Class UserObject
    Public Property Id As Long
    Public Property Name As String
    Public Property Url As String
    Public Property Description As String
    Public Property Link As Uri
    Public Property Slug As String
    <JsonProperty("avatar_urls")>
    Public Property AvatarUrls As Dictionary(Of String, Uri)
    Public Property Meta As List(Of Object)
    <JsonProperty("_links")>
    Public Property Links As Links
End Class

Public Class Links
    Public Property Self As List(Of LinkCollection)
    Public Property Collection As List(Of LinkCollection)
End Class

Public Class LinkCollection
    Public property Href As Uri
End Class

使用此模型,您可以简单地使用JsonConvert.DeserializeObject(),指定要反序列化到的类型。
如前所述,这是一个对象数组或列表,其中基础对象是 UserObject,因此您可以指定 List(Of UserObject)

Dim json = JsonConvert.DeserializeObject(Of List(Of UserObject))(json)

然后您可以照常访问类对象:

Imports System.Net
Imports Newtonsoft.Json
        
Dim users As List(Of UserObject) = Nothing

Using client As New WebClient()
    Dim json = client.DownloadString([The URL])
    users = JsonConvert.DeserializeObject(Of List(Of UserObject))(json)
End Using

If users IsNot Nothing Then
    For Each user In users
        Console.WriteLine(user.Slug)
        Console.WriteLine(user.Links.Self(0).Href)
        Console.WriteLine(user.Links.Collection(0).Href)

        For Each avatar In user.AvatarUrls
            Console.WriteLine($"Key: {avatar.Key}, Value: {avatar.Value}")
        Next
    Next
End If

如果您只需要其中一个属性(在本例中为slug),您可以使用JArray.Parse() 解析 JSON 并直接读取属性值:

Using client As New WebClient()
    Dim json = client.DownloadString([The URL])
    Dim users = JArray.Parse(json)
    For Each user As JToken In users
        Console.WriteLine(user("slug"))
    Next
End Using

【讨论】:

  • 非常感谢Jimi,第二种方法效果很好,也不那么复杂。
【解决方案2】:

虽然 Jimi 的答案更可取,因为它将 JSON 反序列化为强类型对象,但这里有一个替代方案,因为您只关心从对象数组中获取单个属性。

它执行以下三个步骤:

  1. 从端点获取 JSON
  2. 将 JSON 文字转换为 JArray
  3. 使用 LINQ 仅获取数组中每个对象的 Slug
Dim myJsonString = New System.IO.StreamReader(New System.Net.WebClient().OpenRead("http://www.stginternational.org/wp-json/wp/v2/users")).ReadToEnd
Dim arrayOfObjects = JArray.Parse(myJsonString)
Dim arrayOfSlugs = From jsonObject In arrayOfObjects Select jsonObject.Item("slug")

示例:Live Demo

【讨论】:

  • 谢谢大卫,但我终于用 Jimi 的方法成功了,感谢您的帮助。
  • 没问题! Jimi's 确实是更好的选择,我只是想为您提供另一种选择。
猜你喜欢
  • 1970-01-01
  • 2020-10-02
  • 1970-01-01
  • 1970-01-01
  • 2017-07-03
  • 1970-01-01
  • 1970-01-01
  • 2016-02-18
  • 1970-01-01
相关资源
最近更新 更多