如何使用 Json.Net 反序列化嵌套的 JSON 数组?
How to deserialize nested JSON arrays with Json.Net?
我想反序列化 HTTP 请求对对象的响应。
响应如下所示:
[
"BeginOfEnumerable",
[
{
"StatusID": 12345,
"ItemID": 987654
}
],
"EndOfEnumerable"
]
我正在使用 Newtonsoft.Json。
我尝试使用 Visual Studio 的 Edit > Paste special > Paste JSON as Classes
来创建 class 模型,但结果对我来说很奇怪:
Public Class Rootobject
Public Property Property1() As Object
End Class
此外,这会引发异常:
Dim myObject As Rootobject = JsonConvert.DeserializeObject(response.Content)
» Unexpected character encountered while parsing value: .Path ", line
0, position 0.
我想要 StatusID
和 ItemID
。
我使用的 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))()
其中 returns 包含值的 EnumObject
列表,如果这就是您感兴趣的全部并且您不需要以任何其他方式处理此 JSON ,或以相同的形式将其序列化。
如果您只想获得数组的 JSON 表示:
Dim justTheArraysJson = jsonEnumsTokens.Children.Skip(1).First().ToString()
如果你想执行反序列化和序列化,维护结构,你可以使用自定义的 JsonConverter 来处理这个 case.
EnumObjectsConverter
创建一个 中间 结构,其中包含单个字符串和值数组,包含在 EnumObjectArray
属性 .
如果需要,这还允许序列化回原始结构。
称其为:
Dim enumArray = EnumObjectsHandler.Deserialize(response.Content)
Dim serialized = EnumObjectsHandler.Serialize(enumArray)
提供序列化静态方法的EnumObjectsHandler
class:
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
我想反序列化 HTTP 请求对对象的响应。
响应如下所示:
[
"BeginOfEnumerable",
[
{
"StatusID": 12345,
"ItemID": 987654
}
],
"EndOfEnumerable"
]
我正在使用 Newtonsoft.Json。
我尝试使用 Visual Studio 的 Edit > Paste special > Paste JSON as Classes
来创建 class 模型,但结果对我来说很奇怪:
Public Class Rootobject
Public Property Property1() As Object
End Class
此外,这会引发异常:
Dim myObject As Rootobject = JsonConvert.DeserializeObject(response.Content)
» Unexpected character encountered while parsing value: .Path ", line 0, position 0.
我想要 StatusID
和 ItemID
。
我使用的 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))()
其中 returns 包含值的 EnumObject
列表,如果这就是您感兴趣的全部并且您不需要以任何其他方式处理此 JSON ,或以相同的形式将其序列化。
如果您只想获得数组的 JSON 表示:
Dim justTheArraysJson = jsonEnumsTokens.Children.Skip(1).First().ToString()
如果你想执行反序列化和序列化,维护结构,你可以使用自定义的 JsonConverter 来处理这个 case.
EnumObjectsConverter
创建一个 中间 结构,其中包含单个字符串和值数组,包含在 EnumObjectArray
属性 .
如果需要,这还允许序列化回原始结构。
称其为:
Dim enumArray = EnumObjectsHandler.Deserialize(response.Content)
Dim serialized = EnumObjectsHandler.Serialize(enumArray)
提供序列化静态方法的EnumObjectsHandler
class:
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