gpt4 book ai didi

json - 当 JSON 属性可以是单个字符串或带有 Newtonsoft 的 jarray 时,反序列化它

转载 作者:行者123 更新时间:2023-12-04 09:56:33 26 4
gpt4 key购买 nike

我正在从 Web 服务器检索 JSON 响应,并为所有属性创建了强类型类,没有任何问题,但一个属性可以是单个字符串值或嵌套数组。

JSON 示例:

"meta_data": [
{
"id": 12772,
"key": "_shipping_phone",
"value": ""
},
{
"id": 12786,
"key": "status",
"value": "completed"
},
{
"id": 12788,
"key": "Payment type",
"value": "instant"
},
{
"id": 12796,
"key": "_transaction_fee",
"value": "0.39"
},
{
"id": 12806,
"key": "connect_destination_normalized",
"value": "1"
},
{
"id": 12807,
"key": "wc_connect_labels",
"value": [
{
"label_id": 1633947,
"tracking": "9400***************",
"refundable_amount": 3.930000000000000159872115546022541821002960205078125,
"created": 1589499950667,
"carrier_id": "usps",
"service_name": "USPS - First Class Mail",
"status": "PURCHASED",
"package_name": "Bubble Mailer",
"product_names": [
"Peace Love And Wine Sub Tshirt"
],
"receipt_item_id": 60476008,
"created_date": 1589499955000,
"main_receipt_id": 46201718,
"rate": 3.930000000000000159872115546022541821002960205078125,
"currency": "USD",
"expiry_date": 1605051955000,
"label_cached": 1589499962000
},
{
"label_id": 1633942,
"tracking": null,
"refundable_amount": 0,
"created": 1589499912741,
"carrier_id": null,
"service_name": "USPS - First Class Mail",
"status": "PURCHASE_ERROR",
"package_name": "Bubble Mailer",
"product_names": [
"Peace Love And Wine Sub Tshirt"
],
"receipt_item_id": -1,
"created_date": 1589499912000,
"error": "The transaction was declined."
},
{
"label_id": 1633913,
"tracking": null,
"refundable_amount": 0,
"created": 1589499712367,
"carrier_id": null,
"service_name": "USPS - First Class Mail",
"status": "PURCHASE_ERROR",
"package_name": "Bubble Mailer",
"product_names": [
"Peace Love And Wine Sub Tshirt"
],
"receipt_item_id": -1,
"created_date": 1589499712000,
"error": "The transaction was declined."
}
]
}

如您所见, value key 是一个普通的字符串值(或空白字符串)。然而,正如最终条目所示,它可以更多。

这是我的强类型类:
Public Class Meta_Data
Public Property id As Integer
Public Property key As String
'<JsonConverter(GetType(SingleOrArrayConverter(Of Values())))>
Public Property value As Values()
End Class

Public Class Values
Public Property label_id As Integer
Public Property tracking As String
Public Property refundable_amount As String
Public Property created As String
Public Property carrier_id As String
Public Property service_name As String
Public Property status As String
Public Property package_name As String
Public Property product_names As String()
Public Property receipt_item_id As String
Public Property created_date As String
Public Property [error] As String
Public Property main_receipt_id As String
Public Property rate As String
Public Property currency As String
Public Property expiry_date As String
Public Property label_cached As String
End Class

我已经在互联网上搜索了解决方案,但无法想出一个。我尝试了我发现的不同转换器示例,但没有一个工作,因为它们仍然尝试通过 Values 传递单个字符串。类(class)。

这是我的反序列化调用:
Dim info As Order = JsonConvert.DeserializeObject(Of Order)(responseFromServer)

我有多个其他类,我不会占用空间显示,但根类称为 Order .
基本上,有没有办法检查 value在处理反序列化时查看它是否是一个字符串,并防止它通过 Values 进行处理。类(class)?

最佳答案

由于您希望以不同于数组的方式处理单个字符串值,因此您需要更改模型以使其具有多态性。也就是说,创建一个包含 id 的基类。和 key所有人共有的属性 meta_data项,然后创建子类来表示字符串和数组变体。所以,像这样:

Public Class Order
Public Property meta_data As List(Of BaseMetaData)
End Class

<JsonConverter(GetType(MetaDataConverter))>
Public Class BaseMetaData
Public Property id As Integer
Public Property key As String
End Class

Public Class StringMetaData
Inherits BaseMetaData
Public Property value As String
End Class

Public Class ComplexMetaData
Inherits BaseMetaData
Public Property value As List(Of Values)
End Class

Public Class Values
Public Property label_id As Integer
Public Property tracking As String
Public Property refundable_amount As String
Public Property created As String
Public Property carrier_id As String
Public Property service_name As String
Public Property status As String
Public Property package_name As String
Public Property product_names As String()
Public Property receipt_item_id As String
Public Property created_date As String
Public Property [error] As String
Public Property main_receipt_id As String
Public Property rate As String
Public Property currency As String
Public Property expiry_date As String
Public Property label_cached As String
End Class

然后就可以定制 JsonConverter对于检测值类型并创建正确子类的基类:
Public Class MetaDataConverter
Inherits JsonConverter

Public Overrides Function CanConvert(objectType As Type) As Boolean
Return GetType(BaseMetaData).IsAssignableFrom(objectType)
End Function

Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim jo As JObject = JObject.Load(reader)
Dim val As JToken = jo("value")
Dim meta As BaseMetaData
If val.Type = JTokenType.Array Then
meta = New ComplexMetaData()
Else
meta = New StringMetaData()
End If
serializer.Populate(jo.CreateReader(), meta)
Return meta
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

最后一块是标记 BaseMetaDataJsonConverter属性,我已经在上面的模型声明中完成了。然后您可以像往常一样反序列化,一切都应该“正常工作”。

这是一个工作演示: https://dotnetfiddle.net/3uYXKu

关于json - 当 JSON 属性可以是单个字符串或带有 Newtonsoft 的 jarray 时,反序列化它,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61905410/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com