如何在 vb.net 中使用动态修复命名元素反序列化 Json?
How to deserialize Json with fix named elements dynamically in vb.net?
我正在 vb.net 应用程序(使用 httpclient)中实现 Ameritrade Rest API 的接口。
除其他事项外,我还必须从股票代码列表中查询报价(例如 AMD、MSFT、AMZN 等)。
API 的调用没有问题,我得到了有效的 Json 返回,但是 Json 没有以某种方式返回,我希望如此。
我现在正在寻找处理该问题的最佳方法...
这不是 Rest 的第一个接口 API,我已经实现了。
通常,我在vb.net中实现一个相应的数据class,然后使用JsonConvert(来自Newtonsoft)反序列化Json字符串进入我的数据 class.
示例:
Dim oObject As New DataClass
oObject = JsonConvert.DeserializeObject(Of DataClass)(JsonString)
其中DataClass是根据Json字符串中的数据定义的vb.netclass
问题:
要查询的股票代码列表是 dynamic 并且可以从 api call 更改为 api call.
如果我 - 例如- 在通话中查询 AMD 和 MSFT,我返回(只截取几个字段)以下 Json:
{
"AMD": {
"assetType": "EQUITY",
"symbol": "AMD",
"description": "Advanced Micro Devices, Inc. - Common Stock",
"bidPrice": 92.11
},
"MSFT": {
"assetType": "EQUITY",
"symbol": "MSFT",
"description": "Microsoft Corporation - Common Stock",
"bidPrice": 243.1
}
}
为了能够反序列化 Json,我必须实现以下数据类:
Public Class DataClass
Public Property AMD As AMD
Public Property MSFT As MSFT
End Class
Public Class AMD
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
Public Class MSFT
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
这可行,但绝对是静态的,没有任何意义,因为我必须为任何代码实施a(相同)class,我也许想在功能里查询。
我希望得到一个动态列表,以便我可以按如下方式实现 class:
Public Class DataClass
Public Property TickerDetails As List(Of TickerDetail)
End Class
Public Class TickerDetail
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
这样,我就可以在 TickerDetails 列表中反序列化并遍历列表(无论我查询了哪些符号)。
但是,我无法改变,我通过 API...
得到的东西
问题:
处理这个问题的最佳方法是什么?
您应该创建一个 class 来表示通用股票,然后使用 DeserializeObject 将其反序列化为 Dictionary(Of String, [classname]) ,其中 Key 表示股票代码值代表 class.
看看这个例子:
Public Class Stock
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
'...
Dim stocks = JsonConvert.DeserializeObject(Of Dictionary(Of String, Stock))(response)
示例:Live Demo
首先感谢您的评论。
我现在完全不同了...
我在使用 Ameritrade 时遇到了更多问题 API:
- 一些字段以前导数字命名(52WkHigh 和 52WkLow)和
vb.net 开发人员知道,VB.net 不喜欢 class 中的属性
以前导数字命名
- 所以我不得不“修补”接收到的 Json 数据,并即时将名称更改为其他名称(“52WkHigh”更改为“dble52WkHigh”,“52WkLow”更改为“dble52WkLow”)以便能够反序列化
关于数据class,有什么不好
此外,我终于需要(尽可能快地)数据 table 并且“还有很长的路要走”:
获取数据 -> 反序列化到数据 class -> 遍历数据 class 并超越数据 table.
中的数据
所以..我的新解决方案(使用 JObject):
注:需求:
Imports Newtonsoft.Json.Linq
代码片段:
在内存中创建数据table:
Dim dtErgebnis As New DataTable
Dim drTemp As DataRow
With dtErgebnis.Columns
.Add("symbol", System.Type.GetType("System.String"))
.Add("lastPrice", System.Type.GetType("System.Double"))
.Add("lastSize", System.Type.GetType("System.Int32"))
.Add("quoteTime", System.Type.GetType("System.DateTime")) ' Note: is a Long in Json
...
End With
解析Json-字符串并填充数据table:
通过 httpclient 获取数据(在 JsonString 中)...
Dim oJson As JObject = JObject.Parse(JsonString) ' creates children tokens
Dim results As List(Of JToken) = oJson.Children().ToList
For Each item As JProperty In results
item.CreateReader()
drTemp = dtErgebnis.NewRow() ' create a new row to data table in memory
' Fill the fields
drTemp("symbol") = item.Value("symbol")
drTemp("lastPrice") = item.Value("lastPrice")
drTemp("lastSize") = item.Value("lastSize")
drTemp("quoteTime") = GetUTCDateFromTimeStamp(item.Value("quoteTimeInLong")).AddHours(1) ' original Long
...
' Add the new row to the data table
dtErgebnis.Rows.Add(drTemp)
' Save the changes
dtErgebnis.AcceptChanges()
Next
补充说明:Ameritrade API 返回时间戳一样长(额外的障碍),但我(我也认为你;-)希望它作为日期时间。
因此 Long(我认为这种数据类型来自 Java/Unix)必须“翻译”为 datetime = vb.net 下面的函数 GetUTCDateFromTimeStamp:
Public Function GetUTCDateFromTimeStamp(TimeStamp As Long) As DateTime
Static startTime As New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
Return startTime.AddMilliseconds(TimeStamp)
End Function
补充说明:
因为我想要瑞士时间,所以我在 UTC 时间上加了一小时。
所以..这对我来说是一个很好的解决方案(完全适用于 Ameritrade API)。
而且..速度非常快...(我得到了所有字段的 19 个代码,并在数据网格中显示结果(数据 table))。
总共用时 < 1 秒(“感觉”大约 500 毫秒)
希望这对某人有所帮助...
我正在 vb.net 应用程序(使用 httpclient)中实现 Ameritrade Rest API 的接口。
除其他事项外,我还必须从股票代码列表中查询报价(例如 AMD、MSFT、AMZN 等)。
API 的调用没有问题,我得到了有效的 Json 返回,但是 Json 没有以某种方式返回,我希望如此。
我现在正在寻找处理该问题的最佳方法...
这不是 Rest 的第一个接口 API,我已经实现了。
通常,我在vb.net中实现一个相应的数据class,然后使用JsonConvert(来自Newtonsoft)反序列化Json字符串进入我的数据 class.
示例:
Dim oObject As New DataClass
oObject = JsonConvert.DeserializeObject(Of DataClass)(JsonString)
其中DataClass是根据Json字符串中的数据定义的vb.netclass
问题:
要查询的股票代码列表是 dynamic 并且可以从 api call 更改为 api call.
如果我 - 例如- 在通话中查询 AMD 和 MSFT,我返回(只截取几个字段)以下 Json:
{
"AMD": {
"assetType": "EQUITY",
"symbol": "AMD",
"description": "Advanced Micro Devices, Inc. - Common Stock",
"bidPrice": 92.11
},
"MSFT": {
"assetType": "EQUITY",
"symbol": "MSFT",
"description": "Microsoft Corporation - Common Stock",
"bidPrice": 243.1
}
}
为了能够反序列化 Json,我必须实现以下数据类:
Public Class DataClass
Public Property AMD As AMD
Public Property MSFT As MSFT
End Class
Public Class AMD
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
Public Class MSFT
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
这可行,但绝对是静态的,没有任何意义,因为我必须为任何代码实施a(相同)class,我也许想在功能里查询。
我希望得到一个动态列表,以便我可以按如下方式实现 class:
Public Class DataClass
Public Property TickerDetails As List(Of TickerDetail)
End Class
Public Class TickerDetail
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
这样,我就可以在 TickerDetails 列表中反序列化并遍历列表(无论我查询了哪些符号)。
但是,我无法改变,我通过 API...
问题:
处理这个问题的最佳方法是什么?
您应该创建一个 class 来表示通用股票,然后使用 DeserializeObject 将其反序列化为 Dictionary(Of String, [classname]) ,其中 Key 表示股票代码值代表 class.
看看这个例子:
Public Class Stock
Public Property assetType As String
Public Property symbol As String
Public Property description As String
Public Property bidPrice As Double
End Class
'...
Dim stocks = JsonConvert.DeserializeObject(Of Dictionary(Of String, Stock))(response)
示例:Live Demo
首先感谢您的评论。
我现在完全不同了...
我在使用 Ameritrade 时遇到了更多问题 API:
- 一些字段以前导数字命名(52WkHigh 和 52WkLow)和 vb.net 开发人员知道,VB.net 不喜欢 class 中的属性 以前导数字命名
- 所以我不得不“修补”接收到的 Json 数据,并即时将名称更改为其他名称(“52WkHigh”更改为“dble52WkHigh”,“52WkLow”更改为“dble52WkLow”)以便能够反序列化
关于数据class,有什么不好
此外,我终于需要(尽可能快地)数据 table 并且“还有很长的路要走”:
获取数据 -> 反序列化到数据 class -> 遍历数据 class 并超越数据 table.
中的数据
所以..我的新解决方案(使用 JObject):
注:需求:
Imports Newtonsoft.Json.Linq
代码片段:
在内存中创建数据table:
Dim dtErgebnis As New DataTable
Dim drTemp As DataRow
With dtErgebnis.Columns
.Add("symbol", System.Type.GetType("System.String"))
.Add("lastPrice", System.Type.GetType("System.Double"))
.Add("lastSize", System.Type.GetType("System.Int32"))
.Add("quoteTime", System.Type.GetType("System.DateTime")) ' Note: is a Long in Json
...
End With
解析Json-字符串并填充数据table:
通过 httpclient 获取数据(在 JsonString 中)...
Dim oJson As JObject = JObject.Parse(JsonString) ' creates children tokens
Dim results As List(Of JToken) = oJson.Children().ToList
For Each item As JProperty In results
item.CreateReader()
drTemp = dtErgebnis.NewRow() ' create a new row to data table in memory
' Fill the fields
drTemp("symbol") = item.Value("symbol")
drTemp("lastPrice") = item.Value("lastPrice")
drTemp("lastSize") = item.Value("lastSize")
drTemp("quoteTime") = GetUTCDateFromTimeStamp(item.Value("quoteTimeInLong")).AddHours(1) ' original Long
...
' Add the new row to the data table
dtErgebnis.Rows.Add(drTemp)
' Save the changes
dtErgebnis.AcceptChanges()
Next
补充说明:Ameritrade API 返回时间戳一样长(额外的障碍),但我(我也认为你;-)希望它作为日期时间。 因此 Long(我认为这种数据类型来自 Java/Unix)必须“翻译”为 datetime = vb.net 下面的函数 GetUTCDateFromTimeStamp:
Public Function GetUTCDateFromTimeStamp(TimeStamp As Long) As DateTime
Static startTime As New DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
Return startTime.AddMilliseconds(TimeStamp)
End Function
补充说明:
因为我想要瑞士时间,所以我在 UTC 时间上加了一小时。
所以..这对我来说是一个很好的解决方案(完全适用于 Ameritrade API)。
而且..速度非常快...(我得到了所有字段的 19 个代码,并在数据网格中显示结果(数据 table))。
总共用时 < 1 秒(“感觉”大约 500 毫秒)
希望这对某人有所帮助...