Arrays 使用Newtonsoft JSON.NET使用动态对象ID循环非数组JSON

Arrays 使用Newtonsoft JSON.NET使用动态对象ID循环非数组JSON,arrays,json,vb.net,json.net,json-deserialization,Arrays,Json,Vb.net,Json.net,Json Deserialization,我在用电话。我想循环一个JSON结果集,如果可能的话,不必创建一个单独的类,因为JSON对象比这里显示的要扩展得多 我已经看过了 我的JSON(在帖子底部美化): 我第一次尝试使用JsonTextReader,但在尝试快速访问单个属性时似乎太麻烦了: Dim sBuilder As New StringBuilder Dim reader As JsonTextReader = New JsonTextReader(New StringReader(json)) While reader.Rea

我在用电话。我想循环一个JSON结果集,如果可能的话,不必创建一个单独的类,因为JSON对象比这里显示的要扩展得多

我已经看过了

我的JSON(在帖子底部美化):

我第一次尝试使用
JsonTextReader
,但在尝试快速访问单个属性时似乎太麻烦了:

Dim sBuilder As New StringBuilder
Dim reader As JsonTextReader = New JsonTextReader(New StringReader(json))
While reader.Read
    If reader.Value IsNot Nothing Then
        sBuilder.Append(String.Format("Token: {0}, Value: {1}", reader.TokenType.ToString, reader.Value.ToString))
    Else
        sBuilder.Append(String.Format("Token: {0}", reader.TokenType.ToString))
    End If
    sBuilder.Append("<br/>")
End While
美化JSON

{
    "result": {
        "a326f402f18ab1cd2c4489b07cc3e8f4": {
            "id": "a326f402f18ab1cd2c4489b07cc3e8f4",
            "client_id": 30,
            "broker": [
                {
                    "broker_id": 30,
                    "name": "Andrew",
                    "emailaddress": "andrew@homes.com"
                }
            ],
            "photos": [
                {
                    "small": "https://www.example.com/30/photos/small/66.1427790195-976.jpg",
                    "middle": "https://www.example.com/30/photos/middle/66.1427790195-976.jpg"
                },
                {
                    "small": "https://www.example.com/30/photos/small/31382.1508417843-454.JPG",
                    "middle": "https://www.example.com/30/photos/middle/31382.1508417843-454.JPG"
                }
            ]
        },
        "18aec266ec0c01d126e9715bc17124e2": {
            "id": "18aec266ec0c01d126e9715bc17124e2",
            "client_id": 30,
            "broker": [
                {
                    "broker_id": 30,
                    "name": "Andrew",
                    "emailaddress": "andrew@homes.com"
                }
            ],
            "photos": [
                {
                    "small": "https://www.example.com/30/photos/small/10.1298385655.jpg",
                    "middle": "https://www.example.com/30/photos/middle/10.1298385655.jpg"
                },
                {
                    "small": "https://www.example.com/30/photos/small/10.1298385646.jpg",
                    "middle": "https://www.example.com/30/photos/middle/10.1298385646.jpg"
                }
            ]
        }
    }
}
更新2

此代码返回一个数组

Dim photosTEST As JArray = DirectCast(item("photos"), JArray)
Log("photosTEST length", photosTEST.Count.ToString)
但此代码引发错误:
对象引用未设置为对象的实例

Dim brokers As JArray = DirectCast(item("broker"), JArray)
Log("brokers length", brokers.Count.ToString)

我不明白,因为
broker
只是一个长度为1的数组,对吗?

您可以将
结果
JToken
强制转换为
JObject
并循环其
属性()
集合。每个属性的
是另一个
作业对象
,其中包含您感兴趣的数据(例如
id
客户id
照片
,等等)

以下是一个例子:

Dim obj As JObject = JObject.Parse(json)
Dim result As JObject = DirectCast(obj("result"), JObject)
For Each prop As JProperty In result.Properties()

    Dim item As JObject = DirectCast(prop.Value, JObject)
    Dim id As String = item("id").Value(Of String)
    Dim clientId As Integer = item("client_id").Value(Of Integer)
    Console.WriteLine("id: " & id)
    Console.WriteLine("client id: " & clientId.ToString())

    Dim brokers As JArray = DirectCast(item("broker"), JArray)
    For i As Integer = 0 To brokers.Count - 1
        Dim broker As JObject = DirectCast(brokers(i), JObject)
        Dim brokerId As Integer = broker("broker_id").Value(Of Integer)
        Dim name As String = broker("name").Value(Of String)
        Dim email As String = broker("emailaddress").Value(Of String)
        Console.WriteLine("broker " & i.ToString() & " id: " & brokerId)
        Console.WriteLine("broker " & i.ToString() & " name: " & name)
        Console.WriteLine("broker " & i.ToString() & " email: " & email)
    Next

    Dim photos As JArray = DirectCast(item("photos"), JArray)
    For i As Integer = 0 To photos.Count - 1
        Dim photo As JObject = DirectCast(photos(i), JObject)
        Dim small As String = photo("small").Value(Of String)
        Dim middle As String = photo("middle").Value(Of String)
        Console.WriteLine("photo " & i.ToString() & " small: " & small)
        Console.WriteLine("photo " & i.ToString() & " middle: " & middle)
    Next

    Console.WriteLine()
Next
小提琴:

注意,上面的代码假设示例JSON中的所有对象属性都将始终存在。如果某个特定属性可能不出现,则在尝试使用其值之前,您需要检查该属性上的
无任何内容。例如,您提到,当您尝试访问
代理
计数时,您得到的
对象引用未设置为对象的实例
错误。这告诉我,对于一些结果项,JSON中没有
broker
属性。在这种情况下,您需要更改代码以检查
无任何内容
,如下所示:

    Dim brokers As JArray = DirectCast(item("broker"), JArray)
    If brokers IsNot Nothing Then
        For i As Integer = 0 To brokers.Count - 1
            Dim broker As JObject = DirectCast(brokers(i), JObject)
            Dim brokerId As Integer = broker("broker_id").Value(Of Integer)
            Dim name As String = broker("name").Value(Of String)
            Dim email As String = broker("emailaddress").Value(Of String)
            Console.WriteLine("broker " & i.ToString() & " id: " & brokerId)
            Console.WriteLine("broker " & i.ToString() & " name: " & name)
            Console.WriteLine("broker " & i.ToString() & " email: " & email)
        Next
    End If
            Dim email As String = ""
            If broker("emailaddress") IsNot Nothing Then
                email = broker("emailaddress").Value(Of String)
            End If
类似地,如果代理可能没有电子邮件地址,则您需要执行以下操作:

    Dim brokers As JArray = DirectCast(item("broker"), JArray)
    If brokers IsNot Nothing Then
        For i As Integer = 0 To brokers.Count - 1
            Dim broker As JObject = DirectCast(brokers(i), JObject)
            Dim brokerId As Integer = broker("broker_id").Value(Of Integer)
            Dim name As String = broker("name").Value(Of String)
            Dim email As String = broker("emailaddress").Value(Of String)
            Console.WriteLine("broker " & i.ToString() & " id: " & brokerId)
            Console.WriteLine("broker " & i.ToString() & " name: " & name)
            Console.WriteLine("broker " & i.ToString() & " email: " & email)
        Next
    End If
            Dim email As String = ""
            If broker("emailaddress") IsNot Nothing Then
                email = broker("emailaddress").Value(Of String)
            End If
事实上,如果您发现JSON中有许多属性,您不能指望它们总是存在,那么您可以编写一些扩展方法来帮助简化代码。如果某个特定的
JToken
结果为
Nothing
,则此方法将允许您提供一个默认值来代替它:

Imports System.Runtime.CompilerServices
Imports Newtonsoft.Json.Linq

Module JsonExtensions

    <Extension()>
    Public Function ValueOrDefault(Of T)(token As JToken, defaultValue As T) As T
        If token IsNot Nothing AndAlso token.Type <> JTokenType.Null Then
            Return token.Value(Of T)
        Else
            Return defaultValue
        End If
    End Function

End Module
或:


谢谢您的代码适用于
照片
数组,但在
代理
属性上引发了一个错误(请参见更新2)…您能帮我解释一下原因吗?@Flo-我猜您问题中的示例只是您的“真实”JSON的一个缩短版本?在您发布的更新示例中,您没有理由得到该错误<正如您所建议的,代码>代理
只是长度为1的数组。但是,如果您针对不同的、较长的JSON运行此代码,并且该JSON并不总是为每个结果项提供一个
broker
,那么这将导致您看到的错误。我更新了我的答案,解释了如何修复它。你是对的……新手犯了错误,但意外发现:我从中得到了一个非常好的扩展方法:-)。关于这一点有一个问题:我的JSON
“title”中有这个:null
。当我使用扩展方法:
name=item(“title”).ValueOrDefault(“”
)时,代码仍然失败,因为变量
name
将是
Nothing
,而不是空字符串。如何更改扩展名以解决此问题?@Flo如果JSON包含显式null,我们可以通过查看
JToken.Type
属性来检查它是否为
JTokenType.null
。我已经在回答中更新了扩展方法的代码。
Dim brokers As JArray = item("broker").ValueOrDefault(new JArray())
Dim email As String = broker("emailaddress").ValueOrDefault("")