如何使用JSON.Net反序列化嵌套的JSON数组



我想反序列化HTTP请求对对象的响应
响应如下:

[
"BeginOfEnumerable",
[
{
"StatusID": 12345,
"ItemID": 987654
}
],
"EndOfEnumerable"
]

我正在使用Newtonsoft.Json.

我尝试使用Visual Studio的Edit > Paste special > Paste JSON as Classes来创建类模型,但结果看起来很奇怪:

Public Class Rootobject
Public Property Property1() As Object
End Class

此外,这会引发一个异常:

Dim myObject As Rootobject = JsonConvert.DeserializeObject(response.Content)

»解析值时遇到意外字符:.Path",线0,位置0。

我想得到StatusIDItemID
我使用的JSON验证器表示此JSON有效。

JSON结构是有效的,就其本身而言,对于不遵循name:value模式的字符串,您可能会遇到一些困难。

您只能反序列化值的内部数组,如List(class),例如

Imports System.Collections.Generic
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class EnumObject
Public Property StatusId As Long
Public Property ItemId As Long
End Class
'[...]
Dim jsonEnumsTokens = JArray.Parse(response.Content)
Dim enumsArray = jsonEnumsTokens.Children.Skip(1).First().ToObject(Of List(Of EnumObject))()

它返回包含值的EnumObject的列表,如果这是您感兴趣的全部内容,并且您不需要以任何其他方式处理此JSON,或者以相同的形式将其序列化。

如果您只想获得数组的JSON表示:

Dim justTheArraysJson = jsonEnumsTokens.Children.Skip(1).First().ToString()

如果您想执行反序列化和序列化,并维护结构,则可以使用自定义JsonConverter来处理情况

EnumObjectsConverter创建一个中间结构,该结构包含EnumObjectArray属性中包含的单个字符串和值数组
如果需要,这还允许序列化回原始结构。

称之为:

Dim enumArray = EnumObjectsHandler.Deserialize(response.Content)
Dim serialized = EnumObjectsHandler.Serialize(enumArray)

为序列化提供静态方法的EnumObjectsHandler类:

Public Class EnumObjectsHandler
Private Shared settings As JsonSerializerSettings = New JsonSerializerSettings() With {
.Converters = {New EnumObjectsConverter()}
}
Public Shared Function Deserialize(json As String) As List(Of EnumObjectsRoot)
Return JsonConvert.DeserializeObject(Of List(Of EnumObjectsRoot))(json, settings)
End Function
Public Shared Function Serialize(data As List(Of EnumObjectsRoot)) As String
Return JsonConvert.SerializeObject(data, settings)
End Function
Public Class EnumObject
Public Property StatusId As Long
Public Property ItemId As Long
End Class
Public Structure EnumObjectsRoot
Public Property EnumObjectArray As List(Of EnumObject)
Public Property Operation As String
Public Shared Widening Operator CType(objectArray As List(Of EnumObject)) As EnumObjectsRoot
Return New EnumObjectsRoot With {.EnumObjectArray = objectArray}
End Operator
Public Shared Widening Operator CType(op As String) As EnumObjectsRoot
Return New EnumObjectsRoot With {.Operation = op}
End Operator
End Structure

Friend Class EnumObjectsConverter
Inherits JsonConverter
Public Overrides Function CanConvert(t As Type) As Boolean
Return t Is GetType(EnumObjectsRoot)
End Function
Public Overrides Function ReadJson(reader As JsonReader, t As Type, existingValue As Object, serializer As JsonSerializer) As Object
Select Case reader.TokenType
Case JsonToken.String
Dim stringValue = serializer.Deserialize(Of String)(reader)
Return New EnumObjectsRoot() With {
.Operation = stringValue
}
Case JsonToken.StartArray
Dim arrayValue = serializer.Deserialize(Of List(Of EnumObject))(reader)
Return New EnumObjectsRoot() With {
.EnumObjectArray = arrayValue
}
End Select
Throw New Exception("EnumObjectsRoot could not be deserialized")
End Function
Public Overrides Sub WriteJson(writer As JsonWriter, untypedValue As Object, serializer As JsonSerializer)
Dim value = CType(untypedValue, EnumObjectsRoot)
If value.Operation IsNot Nothing Then
serializer.Serialize(writer, value.Operation)
Return
End If
If value.EnumObjectArray IsNot Nothing Then
serializer.Serialize(writer, value.EnumObjectArray)
Return
End If
Throw New Exception("EnumObjectsRoot could not be serialized")
End Sub
End Class
End Class

最新更新