如何反序列化可以是数组或单个对象的JSON [英] How to deserialize JSON which can be an array or a single object
问题描述
我刚开始使用JSON.net并遇到一些json麻烦,所以我有时会以数组的形式出现,有时以单个对象的形式出现.这是我在json中看到的示例
I'm fairly new to using JSON.net and having trouble with some json I'm getting which sometime comes in as an array and sometimes as single object. Here is an example of what I'm seeing with the json
它进来的一种方式...
One way it comes in ...
{
"Make": "Dodge",
"Model": "Charger",
"Lines": [
{
"line": "base",
"engine": "v6",
"color": "red"
},
{
"line": "R/T",
"engine": "v8",
"color": "black"
}
],
"Year": "2013"
}
它可以进入的另一种方式
Another way it could come in
{
"Make": "Dodge",
"Model": "Charger",
"Lines": {
"line": "base",
"engine": "v6",
"color": "red"
},
"Year": "2013"
}
这是我一直在使用的代码,它在第一种情况下有效,而在第二种情况下抛出异常.一直在网上搜寻实现此方法的方法,并确实陷入困境.
Here is what I've been using for code which works on the first way and throws an exception in the second case. Been scouring the web for ways to implement this and am really stuck.
Public Class jsonCar
Public Property make As String
Public Property model As String
Public Property lines As List(Of jsonCarLines)
Public Property year As String
End Class
Public Class jsonCarLines
Public Property line As String
Public Property engine As String
Public Property color As String
End Class
Module Module1
Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": [{""line"":""base"",""engine"": ""v6"",""color"":""red""},{""line"":""R/T"",""engine"":""v8"",""color"":""black""}],""Year"":""2013""}"
'Private Const json As String = "{""Make"":""Dodge"",""Model"":""Charger"",""Lines"": {""line"":""R/T"",""engine"":""v8"",""color"":""black""},""Year"":""2013""}"
Sub Main()
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
Console.WriteLine("Make: " & car.make)
Console.WriteLine("Model: " & car.model)
Console.WriteLine("Year: " & car.year)
Console.WriteLine("Lines: ")
For Each ln As jsonCarLines In car.lines
Console.WriteLine(" Name: " & ln.line)
Console.WriteLine(" Engine: " & ln.engine)
Console.WriteLine(" Color: " & ln.color)
Console.WriteLine()
Next
Console.ReadLine()
End Sub
End Module
我猜想这可能需要一个自定义的JsonConverter,但是我对如何设置它有点不知所措.
I'm guessing this will likely need a custom JsonConverter, but I'm a bit at a loss as to how to set that up.
推荐答案
以下是如何在链接的重复的问题适用于您的用例.
Here is how to get the SingleOrArrayConverter
solution in the linked duplicate question working for your use case.
首先,这是VB转换的转换器代码.将此并保存到项目中某个位置的类文件中.然后,您可以轻松地在以后的任何情况下重用它.
First, here is the VB-translated converter code. Take this and save it to a class file somewhere in your project. You can then easily reuse it for any future cases like this.
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Linq
Public Class SingleOrArrayConverter(Of T)
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType = GetType(List(Of T))
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim token As JToken = JToken.Load(reader)
If (token.Type = JTokenType.Array) Then
Return token.ToObject(Of List(Of T))()
End If
Return New List(Of T) From {token.ToObject(Of T)()}
End Function
Public Overrides ReadOnly Property CanWrite As Boolean
Get
Return False
End Get
End Property
Public Overrides Sub WriteJson(writer As JsonWriter, value As Object, serializer As JsonSerializer)
Throw New NotImplementedException
End Sub
End Class
现在有了此转换器,只要您拥有一个可以是列表或单个项目的属性,您要做的就是将其声明为类中的列表,然后用SingleOrArrayConverter
类.在您的情况下,看起来像这样:
Now that you have this converter, any time you have a property that can be either a list or a single item, all you have to do is declare it as a list in your class and then annotate that list with a JsonConverter
attribute such that it uses the SingleOrArrayConverter
class. In your case, that would look like this:
Public Class jsonCar
Public Property make As String
Public Property model As String
<JsonConverter(GetType(SingleOrArrayConverter(Of jsonCarLines)))>
Public Property lines As List(Of jsonCarLines)
Public Property year As String
End Class
然后,按照通常的方式反序列化,即可正常使用.
Then, just deserialize as you normally would, and it works as expected.
Dim car As jsonCar = JsonConvert.DeserializeObject(Of jsonCar)(json)
这是一个完整的演示: https://dotnetfiddle.net/msYNeQ
Here is a complete demonstration: https://dotnetfiddle.net/msYNeQ
这篇关于如何反序列化可以是数组或单个对象的JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!