【问题标题】:Checking if a key exists in a nested JSON element using Newtonsoft JSON and VB.NET使用 Newtonsoft JSON 和 VB.NET 检查嵌套 JSON 元素中是否存在键
【发布时间】:2019-09-18 13:13:51
【问题描述】:

在 VB.NET 中使用 Newtonsoft Json 我正在尝试读取 JSON 块中的一些嵌套键/元素。

JSON 看起来像这样,并保存在字符串strSuppliedJSON

{
    "seller": {
        "id": 123,
        "name": "Seller Name",
        "address1": "Seller address1",
        "country": "Seller country"
    },
    "buyer": {
        "id": 987,
        "name": "Buyer name",
        "address1": "Buyer address1",
        "country": "Buyer country"
    },
    "interview": {
        "call_id": 123,
        "vin": "The vin from the machine section",
        "call_date": "2019-12-31 23:59:59",
        "questions": ["Question1", "Question2", "Question3", "Question5", "Question5"],
        "triggers": [{
            "question": "Question1",
            "answers": ["Answer1", "Answer2"]
        }]
    }
}

在读取值之前,我需要使用ContainsKey 确保某些键存在。

以下工作正常:

Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq

' Create a dictionary
Dim dictionary As IDictionary(Of String, JToken) = JObject.Parse(strSuppliedJSON)

' Check if key exists - interview:triggers
If JObject.Parse(dictionary("interview").ToString()).ContainsKey("triggers") = False Then
    strAllChecksPassed = False
    result = "ERROR: JSON element not found: interview:triggers"
End If

但是,当尝试检查或阅读 interview:triggers:question 时,事情会倒塌。

使用这个,失败:

' Check if key exists - interview:triggers
If JObject.Parse(dictionary("interview").ToString()).ContainsKey("triggers") = False Then

    strAllChecksPassed = False
    result = "ERROR: JSON element not found: interview:triggers"

Else

    ' interview:triggers DOES exist, now check if the question exists - interview:triggers:question
    If JObject.Parse(dictionary("interview")("triggers").ToString()).ContainsKey("question") = False Then
        strAllChecksPassed = False
        result = "ERROR: JSON element not found: interview:triggers:question"
    End If

End If

引发错误的行是:

If JObject.Parse(dictionary("interview")("triggers").ToString()).ContainsKey("question") = False Then

错误是:

Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1

然后我尝试创建一个仅包含 interview 元素的子字典。

我用过这个:

' Create a sub-dictionary of just the Interview element
Dim subDictionary As IDictionary(Of String, JToken) = JObject.Parse(dictionary("interview").ToString())

如果我随后执行Response.Write(subDictionary),我现在看到了我的 JSON 的一个较小的子集,正如预期的那样:

{
    "call_id": 123,
    "vin": "The vin from the machine section",
    "call_date": "2019-12-31 23:59:59",
    "questions": ["Question1", "Question2", "Question3", "Question5", "Question5"],
    "triggers": [{
        "question": "Question1",
        "answers": ["Answer1", "Answer2"]
    }]
}

但是当尝试以完全相同的方式使用我的新subDictionary 来查看question 密钥是否存在时:

' Check if key exists - interview:triggers:question
If JObject.Parse(subDictionary("triggers").ToString()).ContainsKey("question") = False Then
    strAllChecksPassed = False
    result = "ERROR: JSON element not found: interview:triggers:question"
End If

我得到完全相同的错误:

Newtonsoft.Json.JsonReaderException: Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1

即使代码行相同!

如何检查我的 JSON 中是否存在嵌套键 interview:triggers:question,它的值是多少?

【问题讨论】:

    标签: json vb.net json.net


    【解决方案1】:

    仔细查看 JSON 中的 "triggers":它实际上是一个对象数组,而不是一个对象。您需要先对数组进行索引,然后才能访问"question"

    还请注意,每次调用 ToString 时,都会重新序列化您刚刚使用 Parse 反序列化的内容。你不需要这样做。将 JSON 解析一次为 JObject,然后重用该对象。

    我的 VB-fu 不是很好;我用 C# 编写了这个然后转换了它,但关键部分是Dim first As JToken = triggers(0)。这将获取第一个数组元素,在其上您可以获取与 "question" 关联的值。

            Dim suppliedObject As JObject = JObject.Parse(strSuppliedJSON)
            Dim interview As JToken = suppliedObject("interview")
            Dim triggers As JToken = If(interview IsNot Nothing, interview("triggers"), Nothing)
    
            If triggers Is Nothing Then
                strAllChecksPassed = False
                result = "ERROR: JSON element not found: interview:triggers"
            Else
                Dim first As JToken = triggers(0)
                Dim question As JToken = If(first IsNot Nothing, first("question"), Nothing)
    
                If question Is Nothing Then
                    strAllChecksPassed = False
                    result = "ERROR: JSON element not found: interview:triggers:question"
                End If
            End If
    

    【讨论】:

      【解决方案2】:

      失败是因为你的路径不正确。

      [] 是一个数组。你写出单个项目的名称(在 {} 内),为你写索引的数组(数字)。

      你为什么要解析多次?使用你已有的,例如:

      Dim JsonResp As JObject = JObject.Parse(<JSON>)
      
      'Now there's multiple ways to do the same, here's one
      If JsonResp ("interview")("triggers")(0)("question") Is Nothing Then
          strAllChecksPassed = False
          result = "ERROR: JSON element not found: interview:triggers:question"
      End If
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-09-26
        • 2013-02-18
        • 1970-01-01
        • 1970-01-01
        • 2023-03-09
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多