JSON files
Posted
#1
(In Topic #133)
Guru

Code
Public Sub Main()
Dim vNew As Variant
Dim sNew As String
Shell "wget -O - https://poloniex.com/public?command=returnTicker" To sNew
vNew = Json.decode(sNew) ''Requires component 'gb.web'
Print vNew["BTC_BCN"]["last"]
Stop
EndI am looking to get a list of 'Keys' into an array ["BTC_BCN","BTC_BELA",…] and ["id","last","lowestAsk"…]. Any ideas appreciated.
Posted
Regular

Code
Public Sub Main()
Dim vNew As Variant
Dim sNew As String
Dim cBitcoin As Collection
Dim ciBitcoin As Collection
Shell "wget -O - https://poloniex.com/public?command=returnTicker" To sNew
vNew = Json.decode(sNew) ''Requires component 'gb.web'
cBitcoin = vNew
' Print cBitcoin.Length
For Each ciBitcoin In cBitcoin
Print cBitcoin.Key, cBitcoin[cBitcoin.Key]["last"]
Next
Stop
End
Posted
Guru

Posted
Regular

So I've taken the variant vNew (which is returned from Json.Decode) and copied it into the new collection cBitcoin. Then I enumerate each item in the collection cBitcoin by asking: "FOR EACH collection (ciBitcoin) IN the collection (cBitcoin) please return the Key"
The collection property cBitcoin.Key returns each collection key as a string (e.g. BTC_ETH). And then I can use:
Code
cBitcoin[cBitcoin.Key]["last"]
In VB6 you could also access a collection using a numeric index, something like:
Code
strKeyName = cBitcoin[2].Name
I'm glad you used the Poloniex api query: "https://poloniex.com/public?command=returnTicker"
..as the main collection only references sub-collections, which makes the code straight forward.
As an additional exercise, I spent an hour or two this morning trying to do the same thing with:
"https://www.cryptocompare.com/api/data/coinlist/"
This collection includes a mixture of strings and collections, and I can't think how to deal with this.
What additional data are you trying to retrieve? The remaining data for each trading pair in your example is similar to "last". So for example, if you wanted the 24hr High value use:
Code
cBitcoin[cBitcoin.Key]["high24hr"]
And if you want to filter trading pairs, you could just display Ether markets:
Code
For Each ciBitcoin In cBitcoin
If InStr(cBitcoin.Key, "ETH") > 0 Then
Print cBitcoin.Key, cBitcoin[cBitcoin.Key]["last"], cBitcoin[cBitcoin.Key]["high24hr"]
Endif
Next
I hope this helps, but come back if its still gibberish.
Posted
Regular

As an additional exercise, I spent an hour or two this morning trying to do the same thing with:
"https://www.cryptocompare.com/api/data/coinlist/"
This collection includes a mixture of strings and collections, and I can't think how to deal with this.
I think that should be pretty easy actually. A recursive function to do the data extraction, and start it with a test like this:/lang/is - Gambas Documentation
(Haven't actually run this code)
Posted
Regular

Code
Shell "wget -O - https://www.cryptocompare.com/api/data/coinlist/" To sNew
cBitcoin = Json.decode(sNew, True)
For Each ciBitcoin In cBitcoin["Data"]
strCrypto.Resize(intCoinCount + 1)
strCrypto.Add(ciBitcoin["Name"] & ":" & ciBitcoin["CoinName"])
Inc intCoinCount
Next
strCrypto.Sort 'sort them in alpha order
For index = 0 To strCrypto.Count - 1
Print strCrypto[index]
Next
Print "Total:", intCoinCount
Wow! there are 1507 cryptos listed on this site!
The important bit is the For Each line that just enumerates the "Data" object in the json text. The rest just puts the text into an array and creates pretty-text.
Posted
Guru

Your solution worked but confused me as I have only ever enumerated with the variable after 'Each' not with the variable after 'In'
e.g.
For Each ciBitcoin In cBitcoin
Print ciBitcoin.Key
Next
But you worked with ciBitcoin, it works but I can't work out the logic here.
For Each ciBitcoin In cBitcoin
Print cBitcoin.Key
Next
I was trying to get a list of the other keys as well ["id","last",lowestAsk"…].
Using your example website you end up with a list of keys ["Response", "Message"…"Data"…] then ["LC", "HEAT", "EXB"…] and open up the Collection and there are more keys ["id", "Url", "ImageUrl"…].
Basically I can get the information out as I can see keys like "last" but I thought it would be nice for Gambas to get all that detail for me.
Posted
Regular

cogier said
…Your solution worked but confused me as I have only ever enumerated with the variable after 'Each' not with the variable after 'In'
e.g.
For Each ciBitcoin In cBitcoin
Print ciBitcoin.Key
Next
But you worked with ciBitcoin, it works but I can't work out the logic here.
For Each ciBitcoin In cBitcoin
Print cBitcoin.Key
Next
Take a look at this For Each…In… example:-
Code
Public Sub Main()
Dim Cars As New Collection
Dim Make As String
Cars["Ford"] = 2
Cars["Audi"] = 1
Cars["Jaguar"] = 4
Cars["Lada"] = 3
For Each Make In Cars
Print Make;
Next
End
This "Cars" collection consists of 4 string elements, each one has an integer value assigned to it.
We could print the integer value of an individual element by directly addressing the element, e.g.
Code
Print Cars["Lada"]…would result in: 3
But by creating a string variable ("Make") we can specify that we want to step through each string element in Cars, assign it to Make and then print the corresponding integer value for Make. The result is that the integers are printer in the order they appear in the collection: 2 1 4 3
In the Crypto example, I am not looking for a string element in the Collection, I'm looking for other Collection elements. So I Dim a collection ("ciBitcoin") and use this:-
Code
For Each ciBitcoin In cBitcoin
Posted
Regular

Although the Cars example appears to work, the variable "Make" should be an integer, not a string. The reason it appears to work as a string is that Gambas just quietly converts each integer into a string.
Even if you replace the integers in this example with booleans (True or False) the code still runs without error, but converts True to "T" and false to "".
Posted
Guru

Code (gambas)
- vNew = Json.decode(sNew) ''Requires component 'gb.web'
- cCol = vNew
- GetCollectionData(cCol1)
- GetCollectionData(v)
This got me: -
Key: id Value: 7
Key: id Value: 8
Key: id Value: 10
Key: id Value: 12
Key: id Value: 13
Key: id Value: 14
…….
Thanks for the explanation SteveDee
I discussed it with #3 son last night (he is doing Computer Science at Uni, but does not code in Gambas)
Going to the pub now, I will get a friend to look at all this and see if he can add anything to this debate.
Posted
Regular

Posted
Guru

This code will get the 'Keys' of the 1st and 2nd depth.
Code (gambas)
- vNew = Json.decode(sNew) ''Requires component 'gb.web'
- cCol = vNew
Result
…..
BTC_OMG
ETH_OMG
BTC_GAS
ETH_GAS
id
last
lowestAsk
highestBid
percentChange
baseVolume
quoteVolume
isFrozen
high24hr
low24hr
Posted
Regular

Your code works but the 'TypeOf (v)' is never 'True' so is not called.
I suppose that's because your JSON file does not produce collections inside a collection, as with stevedee?!
Posted
Trainee
TypeOf(v) is true, if you pass the whole result from Json.decode… see below
Code (gambas)
- vNew = Json.decode(sNew) 'Requires component 'gb.web'
- GetCollectionData(vNew)
- GetCollectionData(v)
Results:
Collection: Key: BTC_BCN
Key: id Value: 7
Key: last Value: 0.00000034
Key: lowestAsk Value: 0.00000035
Key: highestBid Value: 0.00000034
Key: percentChange Value: -0.02857142
Key: baseVolume Value: 39.58161827
Key: quoteVolume Value: 115639167.85117029
Key: isFrozen Value: 0
Key: high24hr Value: 0.00000036
Key: low24hr Value: 0.00000033
Collection: Key: BTC_BELA
Key: id Value: 8
Key: last Value: 0.00003115
…
Cheers
Matt
Matt
Posted
Trainee
I think the "Collection" could do with a ".Keys" as well as ".Key" function…. ?
In the meantime, see my GetKeys(Collection) function below:
Code (gambas)
- vNew = Json.decode(sNew) 'Requires component 'gb.web'
- Keys1 = GetKeys(vNew)
- Keys2 = GetKeys(vNew[Keys1[0]])
- Return Keys
Cheers
Matt
Cheers
Matt
Matt
Posted
Regular

Posted
Regular

I think the "Collection" could do with a ".Keys" as well as ".Key" function…. ?
Agree 8-)
Posted
Trainee
anyone can help ?
<IMG src="https://pix.cobrasoftwares.org/images/2022/03/28/Screenshot-from-2022-03-28-21-57-02.png">
Posted
Guru

Try going to Project > Properties… > Components and ensure you have the gb.util.web component loaded.
<IMG src="https://www.cogier.com/gambas/Json1.png">
</IMG>
Posted
Trainee
Does anyone know what i may be doing wrong here? Any help is appreciated.
Code
' Gambas class file
Public Sub Form_Open()
Dim myhttp As HttpClient
Dim cadena_respuesta As String
Dim cadena_peticion As String
Dim vNew As Variant
Dim sNew As String
Dim Keys1 As String[]
Dim Keys2 As String[]
myhttp = New HttpClient
myhttp.Async = False
myhttp.Timeout = 60
myhttp.URL = "https://poloniex.com/public?command=returnTicker"
myhttp.Get
cadena_respuesta = ""
JSON.Decode(cadena_respuesta)
sNew = cadena_respuesta
Print cadena_respuesta
vNew = Json.decode(sNew) 'Requires component 'gb.web'
Keys1 = GetKeys(vNew)
Keys2 = GetKeys(vNew[Keys1[0]])
Print Keys1[0]
Print Keys1[1]
Print Keys2[0]
End
Public Sub GetKeys(Col As Collection) As String[]
Dim Keys As New String[]
Dim v As Variant
For Each v In Col
Keys.Add(Col.Key)
Next
Return Keys
End
Posted
Guru

I suggest you start a 'New Topic' next time you have a question.
Tip: - When adding Gambas code to your posts use the 'gb' button. The code looks a lot better, see below
<IMG src="https://www.cogier.com/gambas/gb_button.png">
</IMG> Regarding your query, put the code below in a Graphical Application and run it, hopefully it will answer some of your questions.
Code (gambas)
- ' Gambas class file
- ''*******************************
- ''REQUIRES gb.net.curl and gb.web
- ''*******************************
- BuildForm
- GetData
- myhttp.Timeout = 60
- myhttp.URL = "https://poloniex.com/public?command=returnTicker"
- myhttp.Get
- vResult = JSON.Decode(sResult)
- GridViewData[iRow, 1].Text = sVal
- Inc iRow
- Inc iRow
- GridViewData.Columns.Width = -1
- .Height = 1000
- .Width = 500
- .Padding = 5
- .Arrangement = Arrange.Vertical
- .Center
- .Columns.Count = 2
- .Columns[0].Title = "Key"
- .Columns[1].Title = "value"
Posted
Trainee
I made some small adjustements to the code you provide before so instead i can get the data collection printed in a terminal.
This is how it looks:
Code (gambas)
- myhttp.Timeout = 60
- myhttp.URL = "https://poloniex.com/public?command=returnTicker"
- myhttp.Get
- vResult = JSON.Decode(sResult)
- Print "____________________________"
Just one last question.
For some reason, when i try to change the url from this example to this one:
https://jsonplaceholder.typicode.com/users
it gives me an error telling me "Wanted string, got Collection instead"
<IMG src="https://ibb.co/54RGPZP">
why is this? and do you know how could i adapt this code to work with this specific Url?
thanks for all the support.
Posted
Guru

url strings were added to the URL by the forum and should not be there (Charlie forgot to select the "Do not automatically parse URLs" option)
this is not right…
Code (gambas)
- myhttp.URL = "<a href="https://poloniex.com/public?command=returnTicker" class="postlink">https://poloniex.com/public?command=returnTicker</a>"
it should just be this..
Code (gambas)
- myhttp.URL = "https://poloniex.com/public?command=returnTicker"
or this even
Code (gambas)
- myhttp.URL = "https://jsonplaceholder.typicode.com/users"
Posted
Guru

Did you include the "<a href=" parts by mistake?
url strings were added to the URL by the forum and should not be there (Charlie forgot to select the "Do not automatically parse URLs" option)
Opps! :?
I have fixed this.
The reason that the new URL creates a crash is due to the fact that there are Collections inside the Collections and I notice, there is another Collection inside that!
<IMG src="https://www.cogier.com/gambas/Collections.png">
</IMG>The code below will skip over the error. Programming the code further depends on what your program is expecting to achieve.
Code (gambas)
- ' Gambas class file
- ''*******************************
- ''REQUIRES gb.net.curl and gb.web
- ''*******************************
- BuildForm
- GetData
- myhttp.Timeout = 60
- myhttp.URL = "https://jsonplaceholder.typicode.com/users"
- myhttp.Get
- vResult = JSON.Decode(sResult)
- Inc iRow
- GridViewData.Columns.Width = -1
- .Height = 1000
- .Width = 500
- .Padding = 5
- .Arrangement = Arrange.Vertical
- .Center
- .Columns.Count = 2
- .Columns[0].Title = "Key"
- .Columns[1].Title = "value"
Posted
Trainee
Code (gambas)
- ' Gambas class file
- ''*******************************
- ''REQUIRES gb.net.curl and gb.web
- ''*******************************
- GetData
- myhttp.Timeout = 60
- myhttp.URL = "https://jsonplaceholder.typicode.com/users"
- myhttp.Get
- vResult = JSON.Decode(sResult)
- Print "-------------------------"
The only bad thing is i get different results in the company name. It shows like this "company : (Collection 0x56185d800b98)"
I was thinking i could get around this by adding an if inside the for each so it can change it to Collection or variant depending on the result in vVal but i would need to give it a try.
1 guest and 0 members have just viewed this.



