简体   繁体   English

反序列化 Json 以搜索字符串

[英]Deserialize Json to search for a String

My Program has a TextBox and a Button.我的程序有一个文本框和一个按钮。 I want to be able to enter text (the id, for example "1000") into that textbox, and when I Press the button it searches in a Json String for all the entries with the ID "1000" and outputs the description of it.我希望能够在该文本框中输入文本(ID,例如“1000”),当我按下按钮时,它会在 Json 字符串中搜索 ID 为“1000”的所有条目并输出它的描述. (there are multiple entries with the same id 1000 so i need a collection). (有多个条目具有相同的 id 1000,所以我需要一个集合)。

But using my Code I always get the Error:但是使用我的代码我总是得到错误:

Cannot deserialize the current JSON object (eg {"name":"value"}) into type 'System.Collections.Generic.List`1[MyProgram.MyObject2]' because the type requires a JSON array (eg [1,2,3]) to deserialize correctly. Cannot deserialize the current JSON object (eg {"name":"value"}) into type 'System.Collections.Generic.List`1[MyProgram.MyObject2]' because the type requires a JSON array (eg [1,2, 3])正确反序列化。 To fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. To fix this error either change the JSON to a JSON array (eg [1,2,3]) or change the deserialized type so that it is a normal .NET type (eg not a primitive type like integer, not a collection type like an数组或列表)可以从 JSON object 反序列化。 JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object. JsonObjectAttribute 也可以添加到类型中以强制它从 JSON object 反序列化。 Path '1000', line 1, position 8."路径‘1000’,第 1 行,position 8。”

I have a json string that looks something like this:我有一个看起来像这样的 json 字符串:

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

I have the class:我有 class:

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

Now I try to deserialize it with:现在我尝试反序列化它:

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

To add all objects from the js string to an object list i use:要将 js 字符串中的所有对象添加到 object 列表中,我使用:

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

Visual Studio has a cool feature called Paste JSON as Classes that can be found under Edit > Paste Special > Paste JSON as Classes . Visual Studio 有一个很酷的功能,称为Paste JSON as Classes可以在Edit > Paste Special > Paste JSON as Classes下找到。 If you think of your JSON as a Dictionary(Of String, CustomClass) then using the Paste JSON as Classes using the class information.如果您将 JSON 视为Dictionary(Of String, CustomClass)然后使用粘贴 JSON 作为使用 class 信息的类

When I do that, I get the following output:当我这样做时,我得到以下 output:

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

Using Newtonsoft, you can clean it up a little bit using decorators:使用 Newtonsoft,您可以使用装饰器对其进行一些清理:

Public Class RootObject

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

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

End Class

Now that the class is setup, you can use the DeserializeObject method (documentation ) to deserialize the JSON into a Dictionary(Of String, RootObject):现在 class 已设置,您可以使用 DeserializeObject 方法(文档)将 JSON 反序列化为 Dictionary(Of String, RootObject):

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

Once you have the Dictionary setup, you can use the ContainsKey method ( documentation ) to check if the entered value is in the collection and if the result returns a value then you can get the class:设置 Dictionary 后,您可以使用 ContainsKey 方法( 文档)检查输入的值是否在集合中,如果结果返回值,则可以获取 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

Example例子

https://dotnetfiddle.net/XmplKB https://dotnetfiddle.net/XmplKB

The message is informing that the Type you asked to deserialize the JSON to, is not representing the JSON structure correctly:该消息通知您要求将 JSON 反序列化为的类型未正确表示 JSON 结构:

Cannot deserialize the current JSON object [...] into type [List] because the type requires a JSON array to deserialize correctly [...]无法将当前 JSON object [...] 反序列化为类型 [List],因为该类型需要 JSON 数组才能正确反序列化 [...]

And suggests to either modify the JSON to an Array or change the Type it deserializes to.并建议将 JSON 修改为数组或将其反序列化为的类型更改。
You of course don't want to change the JSON.您当然不想更改 JSON。

The JSON you posted here is enclosed in braces, so it represents an Object:您在此处发布的 JSON 用大括号括起来,因此它代表 Object:

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

To deserialize to a an Array or List, it should be enclosed in square brackets:要反序列化为数组或列表,应将其括在方括号中:

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

This object contains a sequence of indexed objects.这个 object 包含一系列索引对象。 It's common to deserialize this kind of structure to a Dictionary(Of [Type], [Object]) (as long as the indexes are unique);通常将这种结构反序列化为Dictionary(Of [Type], [Object]) (只要索引是唯一的); using a class model is not really practical (or feasible), since these indexes can vary in number and form.使用 class model 并不实际(或可行),因为这些索引的数量和形式可能会有所不同。

An indexed object here is defined as:此处的索引 object 定义为:

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

You can choose to deserialize the index to either a string or an integer Type (Integer, Long): in this case, the conversion is automatic , there's nothing else to do.您可以选择将索引反序列化为字符串或 integer 类型(整数、长整数):在这种情况下,转换是自动的,没有其他事情可做。
The Object is defined by your MyObject2 Type. Object 由您的MyObject2类型定义。
So, the Dictionary(Of [Type], [Object]) can be a Dictionary(Of String, MyObject2) .因此, Dictionary(Of [Type], [Object])可以是Dictionary(Of String, MyObject2)
You probably prefer to keep the index as a string, since you want to use a TextBox to input the index of the object to look for.您可能更喜欢将索引保留为字符串,因为您想使用文本框输入要查找的 object 的索引。

The deserialization method is then changed in:然后将反序列化方法更改为:

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

To find the description property of an object using its index, you can then just use the Key of your Dictionary:要使用索引查找 object 的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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM