
Question:
I have this JSON data:
<blockquote>{"asks":[["0.26039995",19.91610429],["0.26063345",3070.562292]],"bids":[["0.26000017",30381.45513902],["0.26000000",8299.1410574]],"isFrozen":"0","seq":50663190}
</blockquote>I wrote this code:
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim wc As New WebClient
Dim sURL As String = "https://poloniex.com/public?command=returnOrderBook¤cyPair=USDT_STR&depth=" & 2
Dim res As String = wc.DownloadString(New Uri(sURL))
Dim m As IEnumerable(Of Rootobject) = JsonConvert.DeserializeObject(Of IEnumerable(Of Rootobject))(res)
End Sub
Public Class Rootobject
Public Property asks As asksDef()
Public Property bids As bidsDef()
Public Property isFrozen As String
Public Property seq As Integer
End Class
Public Class asksDef
Public Property priceAsk As String
Public Property quantAsk As Integer
End Class
Public Class bidsDef
Public Property priceBid As String
Public Property quantBid As Integer
End Class
I've pasted the JSON class with VB paste special.
The question is: how to access to every ask
, every bid
and the isFrozen
and seq
values.
I got an error on this line:
Dim m As IEnumerable(Of Rootobject) = JsonConvert.DeserializeObject(Of IEnumerable(Of Rootobject))(res)
The error message I got is:
<blockquote>An unhandled exception of type 'Newtonsoft.Json.JsonSerializationException' occurred in Newtonsoft.Json.dll
Additional information: Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'System.Collections.Generic.IEnumerable`1[poloniexAPI.Rootobject]' because the type requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a collection type like an array or List) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'asks', line 1, position 8.
</blockquote>I'm stuck again this time with this JSON model. How to proceed with this?
<blockquote>{"BTC_BCN":{"id":7,"last":"0.00000042","lowestAsk":"0.00000043","highestBid":"0.00000042","percentChange":"0.00000000","baseVolume":"179.56364789","quoteVolume":"436786711.33832335","isFrozen":"0","high24hr":"0.00000043","low24hr":"0.00000039"},"BTC_BELA":{"id":8,"last":"0.00002091","lowestAsk":"0.00002097","highestBid":"0.00002091","percentChange":"-0.10831556","baseVolume":"12.57891843","quoteVolume":"579476.06165462","isFrozen":"0","high24hr":"0.00002345","low24hr":"0.00002088"}}
</blockquote> Answer1:The root cause of this specific error is that your JSON represents a single object (which contains some arrays and other info) but you are trying to deserialize it as if the whole thing were enumerable. However, fixing this will not solve the whole problem; there are a couple of other issues as well.
This JSON is a little odd because it uses an array to group together each price and quantity pair for the bids and asks, whereas an object seems like it would be more appropriate (and more easily consumable). Since Json.Net does not have a facility to automatically map an array into class properties by index, you will need to use a custom JsonConverter
to deserialize this data properly. Also, the prices are represented as strings for some reason where they should be decimals like the quantity. This can be handled in the converter as well.
Before we get to the converter, let's fix your class definitions. Since the bids and asks use the same structure, I would recommend defining a common class for that. Both price
and quantity
properties should be declared as Decimal
:
Public Class PriceQuantityPair
Public Property price As Decimal
Public Property quantity As Decimal
End Class
Then define your root class like this:
Class RootObject
Public Property asks As List(Of PriceQuantityPair)
Public Property bids As List(Of PriceQuantityPair)
Public Property isFrozen As String
Public Property seq As Integer
End Class
Here is the code for the converter, which will translate the array structure for each pair into a PriceQuantityPair
instance:
Class PriceQuantityPairConverter
Inherits JsonConverter
Public Overrides Function CanConvert(objectType As Type) As Boolean
Return objectType Is GetType(PriceQuantityPair)
End Function
Public Overrides Function ReadJson(reader As JsonReader, objectType As Type, existingValue As Object, serializer As JsonSerializer) As Object
Dim ja As JArray = JArray.Load(reader)
Dim pair As PriceQuantityPair = New PriceQuantityPair()
pair.price = ja(0).ToObject(Of Decimal)()
pair.quantity = ja(1).ToObject(Of Decimal)()
Return pair
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
To use the converter, add a <JsonConverter>
attribute to the PriceQuantityPair
class like this:
<JsonConverter(GetType(PriceQuantityPairConverter))>
Public Class PriceQuantityPair
...
End Class
Finally, deserialize the JSON into the RootObject
class like this:
Dim root As RootObject = JsonConvert.DeserializeObject(Of RootObject)(json)
Here is a demo: <a href="https://dotnetfiddle.net/dDHLtR" rel="nofollow">https://dotnetfiddle.net/dDHLtR</a>
Answer2:As far as I understand your question. You can access the properties with the 'm' variable where you are storing the de serialized data. Ex: m.isFrozen, m.seq, m.bids() & m.asks().