【问题标题】:How to deserialize Json with fix named elements dynamically in vb.net?如何在 vb.net 中通过动态修复命名元素来反序列化 Json?
【发布时间】:2021-02-12 10:16:51
【问题描述】:

我正准备在 vb.net 应用程序(使用 httpclient)中实现 Ameritrade Rest API 的接口。
除其他事项外,我必须从股票代码列表中查询报价(例如 AMD、MSFT、AMZN、....)。
API 的调用没有问题,我得到了一个有效的 Json,但我希望 Json 没有以某种方式返回。
我现在正在寻找解决该问题的最佳方法...

这不是我实现的第一个 Rest API 接口。
通常,我在 vb.net 中实现相应的数据类,然后使用 JsonConvert(来自 Newtonsoft)将 Json 字符串反序列化到我的数据类中。
示例:

 Dim oObject As New DataClass
 oObject = JsonConvert.DeserializeObject(Of DataClass)(JsonString)

其中DataClass是根据Json字符串中的数据定义的vb.net类。

问题:
要查询的股票代码列表是动态的,并且可以从 api 调用更改为 api 调用。
如果我 - 例如- 在通话中查询 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,我必须实现以下 DataClass:

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

这可行,但绝对是静态的,没有任何意义,因为我必须为任何代码实现(相同的)类,我可能想在功能中查询。 p>

我希望得到一个动态列表,以便我可以按以下方式实现该类:

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 得到的东西......

问题:
处理此问题的最佳方法是什么?

【问题讨论】:

标签: json vb.net json.net httpclient


【解决方案1】:

您应该创建一个类来表示通用股票,然后使用 DeserializeObject 将其反序列化为 Dictionary(Of String, [classname]),其中 Key 表示股票代码,value 表示类。

看看这个例子:

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

【讨论】:

  • 嘿 - 感谢您的回答(这似乎有效)!与此同时,我找到了一个(对我来说更好的)解决方案(见我自己的帖子)。如果我没有找到我的新解决方案,我会实施你的。
【解决方案2】:

首先感谢 cmets。 我最终做了完全不同的事情......
我在使用 Ameritrade API 时遇到了更多问题:

  • 某些字段以前导数字(52WkHigh 和 52WkLow)命名,并且 vb.net 开发人员知道,VB.net 不喜欢类中的属性 以前导数字命名
  • 所以我必须“修补”收到的 Json 数据并将名称动态更改为其他名称(“52WkHigh”到“dble52WkHigh”和“52WkLow”到“dble52WkLow”)才能反序列化
    在数据类上,有什么不好的

此外,我终于需要数据表中的数据(尽可能快)并且“还有很长的路要走”:
获取数据 -> 反序列化到数据类 -> 遍历数据类并超越数据表中的数据。
所以.. 我的新解决方案(使用 JObject):
注:需求:

Imports Newtonsoft.Json.Linq

代码 sn-ps:

在内存中创建数据表:

  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-String 并填充数据表:
通过 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 个包含所有字段的代码,并在数据网格中显示结果(数据表))。
总共花费了

希望这对某人有所帮助...

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-09-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-12-28
    相关资源
    最近更新 更多