反序列化 Json 以搜索字符串

Deserialize Json to search for a String

我的程序有一个文本框和一个按钮。我希望能够在该文本框中输入文本(id,例如“1000”),当我按下按钮时,它会在 Json 字符串中搜索 ID 为“1000”的所有条目并输出它的描述。 (有多个条目具有相同的 ID 1000,所以我需要一个集合)。

但是使用我的代码我总是得到错误:

Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.List`1[MyProgram.MyObject2]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly. To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. Path '1000', line 1, position 8."

我有一个 json 字符串,看起来像这样:

{
   "1000": {
      "id": 1000,
      "description":"my description 1000"
    },
    "1001": {
       "id": 1001,
       "description":"my description 1001"
    },
    ...
}

我有 class:

Public Class MyObject2
   Public Property id As Integer
   Public Property description As String
End Class

现在我尝试反序列化它:

 Dim objectList = JsonConvert.DeserializeObject(Of List(Of MyObject2))(result)

要将 js 字符串中的所有对象添加到我使用的对象列表中:

Dim foundItem = objectList.Where(Function(__) __.name.Contains(x))

该消息通知您要求将 JSON 反序列化为的类型未正确表示 JSON 结构:

Cannot deserialize the current JSON object [...] into type [List] because the type requires a JSON array to deserialize correctly [...]

并建议将 JSON 修改为数组或将其反序列化为的类型更改为。
您当然不想更改 JSON.

你在这里贴的JSON是用大括号括起来的,代表一个对象:

{ 
    { [...] },
    { [...] }
}

要反序列化为数组或列表,应将其括在方括号中:

[ 
    { [...] },
    { [...] }
]

此对象包含一系列索引对象。通常将这种结构反序列化为 Dictionary(Of [Type], [Object])(只要索引是唯一的);使用 class 模型并不实​​用(或不可行),因为这些 索引 在数量和形式上可能会有所不同。

此处的索引对象定义为:

"1000": {
   "id": 1000,
   "description":"my description 1000"
 }

您可以选择将索引反序列化为字符串或整数类型(Integer, Long):在这种情况下,转换是自动,没有别的事可做.
对象由您的 MyObject2 类型定义。
所以,Dictionary(Of [Type], [Object]) 可以是 Dictionary(Of String, MyObject2).
您可能更喜欢将索引保留为字符串,因为您希望使用 TextBox 输入要查找的对象的索引。

然后反序列化方法改在:

Dim myObjects = JsonConvert.DeserializeObject(Of Dictionary(Of String, MyObject2))(result) 

要使用对象的索引查找对象的 description 属性,您只需使用字典的键即可:

Dim inputKey = SomeTextBox.Text

' [...]

Dim obj As MyObject2 = Nothing

If myObjects.TryGetValue(inputKey, obj) Then
    Return obj.description
Else
    ' Notify that the Index provided doesn't have a matching value
End If

Visual Studio 有一个很棒的功能,称为 将 JSON 粘贴为 类,可以在 Edit > Paste Special > Paste JSON as Classes 下找到。如果您将 JSON 视为 Dictionary(Of String, CustomClass) 然后使用 将 JSON 粘贴为 类 使用 class 信息.

当我这样做时,我得到以下输出:

Public Class Rootobject
    Public Property id As Integer
    Public Property description As String
End Class

使用 Newtonsoft,您可以使用装饰器稍微清理一下:

Public Class RootObject

    <JsonProperty("id")>
    Public Property Id As Integer

    <JsonProperty("description")>
    Public Property Description As String

End Class

现在 class 已设置,您可以使用 DeserializeObject 方法 (documentation) 将 JSON 反序列化为 Dictionary(Of String, RootObject):

Dim dictionary = JsonConvert.DeserializeObject(Of Dictionary(Of String, RootObject))(json)

设置字典后,您可以使用 ContainsKey 方法 (documentation) 检查输入的值是否在集合中,如果结果 returns 是一个值,那么您可以得到class:

Private ReadOnly _dictionary As Dictionary(Of String, RootObject)
Sub New()
    InitializeComponent()

    ' this example assumes you have the JSON literal stored in a variable named "json"
    _dictionary = JsonConvert.DeserializeObject(Of Dictionary(Of String, RootObject))(json)
End Sub

Private Sub ButtonSearch_Click(sender As Object, e As EventArgs) Handles ButtonSearch.Click
    Dim key = TextBoxSearch.Text
    If (_dictionary.ContainsKey(key)) Then
        Dim result = _dictionary(key)
        ' do something with result.Id or result.Description
    End If
End Sub

例子

https://dotnetfiddle.net/XmplKB