I'm parsing this JSON
{"error":null,"result":{"KIBAUSDT":{"limit":100,"offset":0,"total":2,"records":[{"user":2996434,"id":82873069172,"market":"KIBAUSDT","freeze":"100","fee_stock":"","source":"web","type":1,"side":1,"ctime":1645133452.181028,"mtime":1645133452.181028,"price":"0.00002","amount":"100","taker_fee":"0.0035","maker_fee":"-0.003","left":"100","deal_stock":"0","deal_money":"0","deal_fee":"0","alt_fee":"0","deal_fee_alt":"0","status":0},{"user":2996434,"id":82873306723,"market":"KIBAUSDT","freeze":"100","fee_stock":"","source":"web","type":1,"side":1,"ctime":1645133526.563619,"mtime":1645133546.966621,"price":"0.00001124","amount":"200","taker_fee":"0.0035","maker_fee":"-0.003","left":"100","deal_stock":"100","deal_money":"0.001124","deal_fee":"-0.000003372","alt_fee":"0","deal_fee_alt":"0","status":1}]}},"id":300991746}
which is basically the API of one crypto exchange that is showing the orders that I've opened. I'm using quicktype.io to create the code of a new class file
Imports System
Imports Newtonsoft.Json
Imports Newtonsoft.Json.Converters
Imports System.Runtime.CompilerServices
Namespace OrdiniAperti
Partial Public Class Openorders
<JsonProperty("error")>
Public Property [Error] As Object
<JsonProperty("result")>
Public Property Result As Result
<JsonProperty("id")>
Public Property Id As Long
End Class
Partial Public Class Result
<JsonProperty("KIBAUSDT")>
Public Property Kibausdt As Kibausdt
End Class
Partial Public Class Kibausdt
<JsonProperty("limit")>
Public Property Limit As Long
<JsonProperty("offset")>
Public Property Offset As Long
<JsonProperty("total")>
Public Property Total As Long
<JsonProperty("records")>
Public Property Records As Record()
End Class
Partial Public Class Record
<JsonProperty("user")>
Public Property User As Long
<JsonProperty("id")>
Public Property Id As Long
<JsonProperty("market")>
Public Property Market As String
<JsonProperty("freeze")>
Public Property Freeze As String
<JsonProperty("fee_stock")>
Public Property FeeStock As String
<JsonProperty("source")>
Public Property Source As String
<JsonProperty("type")>
Public Property Type As Long
<JsonProperty("side")>
Public Property Side As Long
<JsonProperty("ctime")>
Public Property Ctime As Double
<JsonProperty("mtime")>
Public Property Mtime As Double
<JsonProperty("price")>
Public Property Price As String
<JsonProperty("amount")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property Amount As Long
<JsonProperty("taker_fee")>
Public Property TakerFee As String
<JsonProperty("maker_fee")>
Public Property MakerFee As String
<JsonProperty("left")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property Left As Long
<JsonProperty("deal_stock")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property DealStock As Long
<JsonProperty("deal_money")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property DealMoney As Long
<JsonProperty("deal_fee")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property DealFee As Long
<JsonProperty("alt_fee")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property AltFee As Long
<JsonProperty("deal_fee_alt")>
<JsonConverter(GetType(ParseStringConverter))>
Public Property DealFeeAlt As Long
<JsonProperty("status")>
Public Property Status As Long
End Class
Partial Public Class Openorders
Public Shared Function FromJson(ByVal json As String) As Openorders
Return JsonConvert.DeserializeObject(Of Openorders)(json, Settings)
End Function
End Class
Public Module Serialize
<Extension()>
Public Function ToJson(ByVal self As Openorders) As String
Return JsonConvert.SerializeObject(self, Settings)
End Function
End Module
Friend Module Converter
Public ReadOnly Settings As JsonSerializerSettings = New JsonSerializerSettings With {
.MetadataPropertyHandling = MetadataPropertyHandling.Ignore,
.DateParseHandling = DateParseHandling.None
}
End Module
Friend Class ParseStringConverter
Inherits JsonConverter
Public Overrides Function CanConvert(ByVal t As Type) As Boolean
Return t Is GetType(Long) OrElse t Is GetType(Long?)
End Function
Public Overrides Function ReadJson(ByVal reader As JsonReader, ByVal t As Type, ByVal existingValue As Object, ByVal serializer As JsonSerializer) As Object
If reader.TokenType = JsonToken.Null Then Return Nothing
Dim value = serializer.Deserialize(Of String)(reader)
Dim l As Long
If Long.TryParse(value, l) Then
Return l
End If
Throw New Exception("Cannot unmarshal type long")
End Function
Public Overrides Sub WriteJson(ByVal writer As JsonWriter, ByVal untypedValue As Object, ByVal serializer As JsonSerializer)
If untypedValue Is Nothing Then
serializer.Serialize(writer, Nothing)
Return
End If
Dim value = CLng(untypedValue)
serializer.Serialize(writer, value.ToString())
Return
End Sub
Public Shared ReadOnly Singleton As ParseStringConverter = New ParseStringConverter()
End Class
End Namespace
and then I'm using the following code in order to parse some of the property I need:
Dim json = Await wc1.DownloadStringTaskAsync("https://api.hotbit.io/api/v1/order.pending?market=KIBA/USDT&offset=0&limit=100&api_key=44812d8f-66d3-01c0-94c3b29305040b03&sign=F3330B924E1873B9C8FAB40A25D7B851")
'deserialize the json
Dim rootObj = Openorders.FromJson(json)
'navigate to Kibausdt
Dim kibausdt = rootObj.Result.Kibausdt
'check total
If kibausdt.Total = 0 Then
RichTextBox1.Text = "0 opened orders"
Else
RichTextBox1.Clear()
'loop through records
For Each record In kibausdt.Records
Dim side As String = record.Side.ToString()
Dim amount As Long = record.Amount
Dim price As String = record.Price.ToString
Dim filled As Long = record.Left
Dim status As String = record.Status.ToString
If side = "1" Then
side = "SELL"
Else
side = ("BUY ")
End If
If status = "1" Then
status = "Hidden order"
Else
status = "Not hidden order"
End If
Dim percentage As Double = ((filled * 100) / amount)
RichTextBox1.Text &= " " & side & " - " & " " & amount & " - " & " " & price.ToString & " - " & " " & percentage.tostring & " % " & " - " & " " & status & vbCr
Next
End If
As you can see the API lack of filled % property, so I'm calculating it with the formula ((filled * 100)/ whole order amount). The code is working when I have 0 order opened and when an order ( or more) is opened but still not filled, so with 0% filled. The problem starts when the order is starting to be filled, so the % increase. As soon as the % moves from 0 I'm getting the error on the class file at the line Throw New Exception("Cannot unmarshal type long")
System.Exception: 'Cannot unmarshal type long'
So I've been looking at the class file code and sow that "left" and "amount" properties are declared as Long. So I've tried to declare them as Double and even as Decimal, So I changed also Dim filled As Long to Dim filled As Double as well as Dim amount as long to Dim amount as Double into the main form. But now, I'm getting the following error on the line Return JsonConvert.DeserializeObject(Of Openorders)(json, Settings)
of the Class File:
Newtonsoft.Json.JsonSerializationException: 'Error setting value to 'Left' on 'HotBit_APIs.OrdiniAperti.Record
How is this behavior possible? What Am I doing wrong? Thanks