How to retrieve the value of "Quotes" in this json format? - json

I'm trying to build an app where I can retrieve live Currency values online.
I was using apilayer and I successfully retrieved the data I wanted except for the final currency value.
I'm not sure how to read the value inside the "quotes" node.
Jason Result from API:
{
"success":true,
"terms":"https:\/\/currencylayer.com\/terms",
"privacy":"https:\/\/currencylayer.com\/privacy",
"timestamp":1514567346,
"source":"USD",
"quotes":{
"USDPHP":49.950001
}
}
Using this:
Dim req As HttpWebRequest
Dim res As HttpWebResponse = Nothing
Dim rdr As StreamReader
req = DirectCast(WebRequest.Create("http://apilayer.net/api/live?access_key=xxKeyRemovedxx&currencies=PHP&format=1"), HttpWebRequest)`
res = DirectCast(req.GetResponse, HttpWebResponse)
rdr = New StreamReader(res.GetResponseStream)
Dim jsonresp As String = rdr.ReadToEnd
Dim jResuldict = JsonConvert.DeserializeObject(Of Dictionary(Of String, `Object))(jsonresp)`
Dim qts = jResuldict.Item("quotes").ToString
MsgBox(qts)
Result is:
{
"USDPHP":49.950001
}
I wanted to retrieve only the value inside USDPHP which is 49.95.
So that I can use that value for conversion.
What am I missing?

It looks like quotes is a nested dictionary of name/decimal pairs. To extract it, you can parse your JSON string to a JToken hierarchy, pick out the "quotes" property with SelectTokens(), then deserialize its value with JToken.ToObject(of Dictionary(of String, Decimal))(). Having done so you can work with as you would with any dictionary, for instance by looping through its key/value pairs with For Each:
' Extract and deserialize quotes dictionary
Dim quotes as Dictionary(of String, Decimal) = JToken.Parse(jsonresp) _
.SelectTokens("quotes") _
.Select(Function(d) d.ToObject(of Dictionary(of String, Decimal))()) _
.SingleOrDefault()
' Show quotes to the user
Console.WriteLine(If(quotes.Count = 1, "There is 1 quote: ", string.Format("There are {0} quotes", quotes.Count)))
For Each pair in quotes
Dim name as String = pair.Key
Dim quote as Decimal = pair.Value
Console.WriteLine(" Quote for {0} is {1}.", name, quote)
Next
Which outputs
There is 1 quote:
Quote for USDPHP is 49.950001.
If you are sure that one and only one "quotes" token will be present, you can simplify that a bit by using SelectToken() rather than SelectTokens():
' Extract and deserialize quotes dictionary
Dim quotes as Dictionary(of String, Decimal) = JToken.Parse(jsonresp) _
.SelectToken("quotes") _
.ToObject(of Dictionary(of String, Decimal))()
Finally, if you happen to know the name USDPHP in advance you can pick out its specific value with SelectToken() then cast it to Decimal with an explicit cast:
Dim quote as Decimal = CType(JToken.Parse(jsonresp).SelectToken("quotes.USDPHP"), Decimal)
Sample working .Net fiddle.

Try this, i have not tested it but it should work
Dim qts = jResuldict.Item("quotes.USDPHP").ToString
MsgBox(qts)

Related

JSON Deserializing list of lists

I have a problem deserializing the following JSON string:
{"error":null,"id":1234,"result":[[["config.param1","111"],["config.param2","1222"]],"Config System",1234]}
My structure is:
Public Structure stuConResponse
Dim [Error] As String
Dim ID As String
Dim Result As List(Of stuSubResults)
End Structure
Public Structure stuSubResults
Public Property X1 As List(Of List(Of String))
Public Property X2 As String
Public Property X3 As String
End Structure
And my code is:
Dim JSonSettings As New Newtonsoft.Json.JsonSerializerSettings
JSonSettings.CheckAdditionalContent = True
JSonSettings.DateParseHandling = Newtonsoft.Json.DateParseHandling.DateTime
JSonSettings.DefaultValueHandling = Newtonsoft.Json.DefaultValueHandling.Ignore
JSonSettings.FloatFormatHandling = Newtonsoft.Json.FloatFormatHandling.DefaultValue
JSonSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
Dim HeloResponse As Structures.stuConResponse = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Structures.stuConResponse)(ReceivedData, JSonSettings)
I tried making "Results" the following:
1) A tuple of (list of (list of (string), string, string))
2) A list of (list of (string))
3) Other lists and tuples combined
For the life of me, I can't deserialise the "result" object whatsoever.
I have no problems reading the error and ID, but when Result comes in, I get the error that JSON can't do it.
I don't also mind if "result" can go into a string un-deserialised where I can do some manual logic, but that also don't work as JSON is trying to be too cleaver.
In other words, the problem is getting JSON to read "[[[X1,Y1],[X2,Y2],X3,X4]", notice that it's a list/array and that it does not have any Key-names which is where the problem is (I think).
It would be great to get your thoughts on this one.
Thanks
Dim JSONC = New JavaScriptSerializer().DeserializeObject(yourjson)
Debug.Print(JSONC("result")(0)(0)(0)) 'get result collection, then first element, then first object then first element of object
You decide what you want to do with the object.
You can convert ii to dictionary then get stuff with ("key") but if the data stays the same I see no point.
Finally, I solved it!, I had no idea that you can use IDICTIONARY to read the whole thing and then break it down into ILISTs...
For anyone who is having the same problem, here is the solution:
1) Code:
Dim I As Integer
Dim ConPolConfig As Structures.stuConPolSubscribeResponse = Nothing
Dim dicItems As IDictionary = Newtonsoft.Json.JsonConvert.DeserializeObject(Of IDictionary)(ReceivedData, JSonSettings)
ConPolConfig.ID = dicItems("id")
ConPolConfig.Error = dicItems("error")
If Not dicItems("result") Is Nothing Then
ConPolConfig.ConfigItems = New List(Of Dictionary(Of String, String))
Dim ConfigProperties As IList = dicItems("result")(0)
Dim ConfSysReader As String = dicItems("result")(1)
Dim Token As Integer = dicItems("result")(2)
Dim ParamKey As String
Dim ParamVal As String
Dim Dic As New Dictionary(Of String, String)
For I = 0 To ConfigProperties.Count - 1
ParamKey = ConfigProperties(I)(0)
ParamVal = ConfigProperties(I)(1)
Dic.Add(ParamKey, ParamVal)
ConPolConfig.ConfigItems.Add(Dic)
Next
End If
2) Structures:
Public Structure stuConPolSubscribeResponse
Dim [Error] As String
Dim ID As String
Dim ConfigItems As List(Of Dictionary(Of String, String))
End Structure
This works and does exactly what I am looking for as per my initial question. i.e. reading a list or lists where the master list has an additional 2 different elements (a string and an integer). the iDictionary would read the whole thing without any errors and then you could iterate it using an ILIST...
Don't ask me why the source JSON string is written in such a way... but now this works to read it...
... I need a coffee ...

Get json value in VB.NET

How can I get the name of a key in a json file? I have a json that I'm parsing in VB.NET and one of the 'fields' have a dynamic name (it changes). What could I do to get the key name?
For example:
...
"one":{
"two":{
"example":[
{
"aaa":"test",
"bbb":"test",
"ccc":"test"
},
...
I'm getting correctly all the values (test, test, test...) and the keys 'one', 'two', have always the same name. But the key 'example' changes the name according the json file information. How could I identify the key text?
I wrote a piece of code that converts JSON into a XDocument here: https://github.com/dday9/.NET-JSON-Transformer
If you were to use that code, then you could get the node that represents your "two" object and then get the first child node in to. By doing this, you're essentially getting the array by an Index instead of by a name.
Here is a quick example of what I mean:
Dim literal As String = "{""two"":{""example"":[{""aaa"":""test"",""bbb"":""test"",""ccc"":""test""}]}}"
Dim xJSON As XDocument = JSON.Parse(literal)
Dim object_two As XElement = xJSON.Descendants("two").FirstOrDefault()
If object_two IsNot Nothing Then
Dim first_descendent As XElement = object_two.Descendants().Skip(1).FirstOrDefault()
If first_descendent IsNot Nothing Then
Console.WriteLine(first_descendent)
End If
End If
Fiddle: Live Demo
This piece will allow to get data from an unknown JSON structure, without having to define a class.
Sample
Dim serializer As System.Web.Script.Serialization.JavaScriptSerializer
serializer = New JavaScriptSerializer()
' {"elements":[{"handle~":{"emailAddress":"myself#example.com"},"handle":"urn:li:emailAddress:348955221"}]}
dim json as string
Dim obj As System.Collections.Generic.IDictionary(Of String, Object)
obj = serializer.Deserialize(Of System.Collections.Generic.IDictionary(Of String, Object))(json)
dim email as string=string.empty
email = If(GetJsonValue(obj, {"elements", "handle~", "emailAddress"}.ToList()), email)
The Function, very self descriptive:
''' <summary>decode json data </summary>
Public Function GetJsonValue(ByVal obj As Object,
ByVal key As List(Of String)) As String
GetJsonValue = Nothing
' If the object is an array, assume any element can contain the key
If obj.GetType Is GetType(Object()) Then
For Each newObj As Object In CType(obj, Object())
Dim tmp As String = GetJsonValue(newObj, key)
If Not String.IsNullOrEmpty(tmp) Then Return tmp
Next
Else
Dim objEle As System.Collections.Generic.IDictionary(Of String, Object)
Dim keyName As String
Dim objKey As String
'
keyName = key(0)
objEle = CType(obj, System.Collections.Generic.IDictionary(Of String, Object))
objKey = objEle.Keys.ToArray()(0)
If objEle.ContainsKey(keyName) Then
Dim temp As Object = objEle.Item(keyName)
If key.Count > 1 Then
' if the element is array, we need to get the array element and move to the next
key.RemoveAt(0)
Return GetJsonValue(temp, key)
Else
Return temp.ToString()
End If
End If
End If
End Function
I see this is solved but would like to suggest another solution for future readers. The JavaScriptSerializer can return a nested dictionary collection (Of String, Object). I find it easier to explore the result in debug while coding. The code below shows an example of how to navigate the collections.
Dim deserializer As New System.Web.Script.Serialization.JavaScriptSerializer
Dim text As String = "{""two"":{""example"":[{""aaa"":""test"",""bbb"":""test"",""ccc"":""test""}]}}"
Dim dict As Dictionary(Of String, Object) = deserializer.DeserializeObject(text)
Dim keys As Dictionary(Of String, Object).KeyCollection
keys = dict("two")("example")(0).Keys
Dim aaaName As String = keys(0)
Dim aaaValue As String = dict("two")("example")(0)(aaaName)

How to simplify this code using newtonsoft or other json parsers?

I got a simple json
{"200567175963759": { "pair": "esp_btc", "type": "sell", "amount": 2000000, "rate": 1E-08, "timestamp_created": "1498114417", "status": 0}}
I want to parse it without creating any new classes. I want to make it easy.
I am using jsonhelper class that I created my self to parse it. It's basically try to find the first thing between two double quotes and got 200567175963759 which is the order id. Get parameter is simply finding something between "pair":" and "
For simple json it works fine. How can I do get order ID, which si 200567175963759, or timestamp, using better parser, like newtonsoft.
I wonder if I can do that using newtonsoft json?
Dim jsonstring = jsonHelper.stripWhiteSpace(order3.ToString) '{"200567175963759": { "pair": "esp_btc", "type": "sell", "amount": 2000000, "rate": 1E-08, "timestamp_created": "1498114417", "status": 0}}
Dim orderid = fGetToken(order3.ToString, 1, """", """")
Dim base = b
Dim quote = key
Dim typeOfOrder = jsonHelper.getParameter(jsonstring, "type")
Dim amount = jsonHelper.getParameter(jsonstring, "amount")
Dim rate = jsonHelper.getParameter(jsonstring, "rate")
Dim timestamp_created = jsonHelper.getParameter(jsonstring, "timestamp_created")
Dim order4 = OrdersAtExchange.createOrders(amount, base, quote, _exchange, timestamp_created, rate, orderid)
_orders.Add(order4)
If I try to parse that using newtonsoft, I got this object whose type is
Dim order = Newtonsoft.Json.JsonConvert.DeserializeObject(jsonorders)
Dim order1 = CType(order, Newtonsoft.Json.Linq.JObject)
Dim order2 = order1.Item("return").ToList
I look at all the method in Newtonsoft.Json.Linq.JObject I can't find anything that say convert dictionary structures in json to say generic.dictionary
There is something like that. I tried but simply didn't work.
So I wonder if there's an actual sample of some code parsing that simple json with newtonsoft?
Object is Type Dictionary, In case if property looks like index or key it probably dictionary
Dim JsonString As String = "{""200567175963759"": { ""pair"": ""esp_btc"", ""type"": ""sell"", ""amount"": 2000000, ""rate"": 1E-08, ""timestamp_created"": ""1498114417"", ""status"": 0}}"
Dim JsonSettings = New Newtonsoft.Json.JsonSerializerSettings
JsonSettings.NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
Dim OutObject = Newtonsoft.Json.JsonConvert.DeserializeObject(Of Dictionary(Of String, SampleType))(JsonString)
Class SampleType
Property pair As String
Property type As String
Property amount As String
Property rate As String
Property timestamp_created As String
Property status As String
End Class
Here is a sample showing how you can parse your JSON using Json.Net's LINQ-to-JSON API (JTokens, JObjects, etc.)
Dim json As String =
"{" &
" ""200567175963759"": {" &
" ""pair"": ""esp_btc""," &
" ""type"": ""sell""," &
" ""amount"": 2000000," &
" ""rate"": 1E-08," &
" ""timestamp_created"": ""1498114417""," &
" ""status"": 0" &
" }" &
"}"
Dim rootObject As JObject = JObject.Parse(json)
For Each prop As JProperty In rootObject.Properties()
Dim orderid As String = prop.Name
Dim orderInfo As JObject = prop.Value
Dim pair As String = orderInfo("pair").ToString()
Dim typeOfOrder As String = orderInfo("type").ToString()
Dim amount As Decimal = orderInfo("amount").ToObject(Of Decimal)
Dim rate As Decimal = orderInfo("rate").ToObject(Of Decimal)
Dim timestamp_created As String = orderInfo("timestamp_created").ToString()
Dim status As Integer = orderInfo("status").ToObject(Of Integer)
'etc. ...
Next
Demo: https://dotnetfiddle.net/X9SPIE

Web API Contoller - What is the proper format of the data to be returned

I have Web API controller that retrieves ticket information. At the start -- The API is called and the request is routed to the proper controller function. The controller passes a request to the database. From there the retrieved data is ran through a dictionary block where the field name is associated with the data. Next the data is serialized. Then the data is passed back to the controller. At this point I know the Json string looks good. But, when the properly formatted json data is passed back to the caller a bunch slashes are added to the output.
My understanding is that Web API is supposed to automatically format the return data. I suspect I am formatting the data for the controller correctly before it is returned.
Public Function GetTicketSearch(ByVal SourceTktNum As String) As Object
'GET api/outage/SourceTktNum
Dim strFullName As String = MethodBase.GetCurrentMethod().ReflectedType.FullName
Dim strMethodName As String = MethodBase.GetCurrentMethod().Name
Dim strClassRoutine As String = strMethodName & " / " & strFullName
Try
Dim objJsonRptRtn As Object = GetReportData_bllBLL.BLL__DataSet__GetReportData__GetData(strMARCLSysId, strLogonSysId, SourceTktNum)
'AT THIS POINT I KNOW THE JSON STRING LOOKS AS IT SHOULD.
Return objJsonRptRtn
'AFTER THE ABOVE STATEMENT SOMETHING HAPPENS TO THE DATA / SLASHES ARE ADDED TO THE OUTPUT TO BE RETURNED BY THE API
Catch ex As Exception
Dim strExMessage As String = ex.Message
Dim strStackTrace As String = ex.StackTrace
Dim strMsg As String = strExMessage & ControlChars.CrLf & ControlChars.Lf & strStackTrace & ControlChars.CrLf & ControlChars.Lf
MailLogEvent.BLL__Process__MailAndLogEvent__AddLogEntry(strMARCLSysId, strLogonSysId, 901020, dteTime_Start, 0, strMsg, strClassRoutine)
Throw New HttpResponseException(HttpStatusCode.InternalServerError)
End Try
End Function
Code to create JSON object to be passed back to the controller...
'--------------------------------------------------------- Create Json String
Dim dctDataDictionary As New Dictionary(Of String, String)
dctDataDictionary.Add("sourceTktNum", strSourceTktNumKey)
dctDataDictionary.Add("incidentTime", strIncidentTime)
dctDataDictionary.Add("incidentEndTime", strIncidentEndTime)
dctDataDictionary.Add("recordTimeStamp", strRecordTimeStamp)
dctDataDictionary.Add("outageReasonCd", strOutageReasonCd)
dctDataDictionary.Add("numDS3", strNumDS3)
dctDataDictionary.Add("numBlocked", strNumBlocked)
dctDataDictionary.Add("numVOIP", strNumVOIP)
dctDataDictionary.Add("numWireline", strNumWireline)
dctDataDictionary.Add("numEndUserCircuits", strNumEndUserCircuits)
dctDataDictionary.Add("stateCd", strStateCd)
dctDataDictionary.Add("city", strCity)
dctDataDictionary.Add("incidentDescription", strIncidentDescription)
dctDataDictionary.Add("causeDesc", strCauseDesc)
dctDataDictionary.Add("equipFailedDesc", strEquipFailedDesc)
dctDataDictionary.Add("networkPartDesc", strNetworkPartDesc)
dctDataDictionary.Add("restoreMethodDesc", strRestoreMethodDesc)
objJsonRptRtn = New System.Web.Script.Serialization.JavaScriptSerializer().Serialize(dctDataDictionary)
Return objJsonRptRtn
This could be happening because you are again trying to convert a json data into json, which results in extra slashes.
Can you show the code before you return 'objJsonRptRtn'.
As it turned out I was double serializing. I removed the statement that serialized the dictionary output. Then, simply passed the dictionary back to the controller then let the controller return the dictionary. Everything works great...
'--------------------------------------------------------- Create Dictionary
dctDataDictionary.Add("sourceTktNum", strSourceTktNumKey)
dctDataDictionary.Add("incidentTime", strIncidentTime)
dctDataDictionary.Add("incidentEndTime", strIncidentEndTime)
dctDataDictionary.Add("recordTimeStamp", strRecordTimeStamp)
dctDataDictionary.Add("outageReasonCd", strOutageReasonCd)
dctDataDictionary.Add("numDS3", strNumDS3)
dctDataDictionary.Add("numBlocked", strNumBlocked)
dctDataDictionary.Add("numVOIP", strNumVOIP)
dctDataDictionary.Add("numWireline", strNumWireline)
dctDataDictionary.Add("numEndUserCircuits", strNumEndUserCircuits)
dctDataDictionary.Add("stateCd", strStateCd)
dctDataDictionary.Add("city", strCity)
dctDataDictionary.Add("incidentDescription", strIncidentDescription)
dctDataDictionary.Add("causeDesc", strCauseDesc)
dctDataDictionary.Add("equipFailedDesc", strEquipFailedDesc)
dctDataDictionary.Add("networkPartDesc", strNetworkPartDesc)
dctDataDictionary.Add("restoreMethodDesc", strRestoreMethodDesc)
Return dctDataDictionary
Public Function GetTicketSearch(ByVal SourceTktNum As String) As Object
'GET api/outage/SourceTktNum
Dim strFullName As String = MethodBase.GetCurrentMethod().ReflectedType.FullName
Dim strMethodName As String = MethodBase.GetCurrentMethod().Name
Dim strClassRoutine As String = strMethodName & " / " & strFullName
Try
Dim dctDataDictionary As Object = GetReportData_bllBLL.BLL__DataSet__GetReportData__GetData(strMARCLSysId, strLogonSysId, SourceTktNum)
If dctDataDictionary Is Nothing Then
Throw New HttpResponseException(HttpStatusCode.PartialContent)
Else
Return dctDataDictionary
End If
Catch ex As Exception
Dim strExMessage As String = ex.Message
Dim strStackTrace As String = ex.StackTrace
Dim strMsg As String = strExMessage & ControlChars.CrLf & ControlChars.Lf & strStackTrace & ControlChars.CrLf & ControlChars.Lf
MailLogEvent.BLL__Process__MailAndLogEvent__AddLogEntry(strMARCLSysId, strLogonSysId, 901020, dteTime_Start, 0, strMsg, strClassRoutine)
Throw New HttpResponseException(HttpStatusCode.InternalServerError)
End Try
End Function

How to read answer in JSON format,and transfer them into labels text

i need some help. I wanna make a program uses the website to search for data,those text come in JSON format,how do i load those files and write them on labels?
like this > {"mature":null,"status":"Chill","broadcaster_language":"en","display_name":"MexxHD","game":"Counter-Strike: Global Offensive"}}
Here is the link i use for read this > https://api.twitch.tv/kraken/channels/MexxHD
I was able to get an "answer" from the website,but i dont know how to print them in labels(here is code what i use)
Dim request As HttpWebRequest = DirectCast(WebRequest.Create("https://api.twitch.tv/kraken/channels/" & TextBox1.Text), HttpWebRequest)
Dim response As HttpWebResponse = DirectCast(request.GetResponse(), HttpWebResponse)
Dim reader As New StreamReader(response.GetResponseStream())
How do i from this > {"mature":null,"status":"Chill","broadcaster_language":"en"..
Move information in labels like Labe1.text to be Chill and label2.text to be en...
A JSON string is not just a complex string - it is serialized data (a class, dictionary, array etc). Nor can you ignore the parts you don't care about: your post leaves off a big chunk at the end.
In this case, it looks like it can be deserialized to a Dictionary, with the last element ("_links") itself being a dictionary. Looking at the text, the first element ("mature") is null, so I use Dictionary(Of String, Object):
Imports Newtonsoft.Json
' I downloaded it for ease, you could use the response
Dim json = File.ReadAllText("C:\Temp\MexxHD.json")
Dim col As Dictionary(Of String, Object)
col = JsonConvert.DeserializeObject(Of Dictionary(Of String, Object))(json)
That's it really. Display the contents (remember at least one value is Nothing):
For Each kvp As KeyValuePair(Of String, Object) In col
Console.WriteLine("Key: {0}, value: {1}", kvp.Key,
If(kvp.Value Is Nothing, "Null", kvp.Value.ToString))
Next
Output:
Key: mature, value: Null
Key: status, value: Chill
Key: broadcaster_language, value: en
Key: display_name, value: MexxHD
(etc)
The links part can be deserialized to its own dictionary:
Dim JLinks = col("_links").ToString
Dim linkCol As Dictionary(Of String, String)
linkCol = JsonConvert.DeserializeObject(Of Dictionary(Of String, String))(JLinks)
Console.WriteLine("********* LINKS ********* ")
For Each kvp As KeyValuePair(Of String, String) In linkCol
Console.WriteLine("K: {0} V: {1}", kvp.Key, kvp.Value)
Next
Output:
********* LINKS *********
K: self V: https://api.twitch.tv/kraken/channels/mexxhd
K: follows V: https://api.twitch.tv/kraken/channels/mexxhd/follows
K: commercial V: https://api.twitch.tv/kraken/channels/mexxhd/commercial
(etc)
When the JSON appears to be an array of class objects, there are online tools which will create the class structure from the JSON string such as this one which will do VB classes
Just fetch the items you want from the Dictionary. Do keep in mind that some values can be Nothing as is the case for "mature" which can lead to a NullReference Exception:
Label1.Text = col("status").ToString()
First do this
Imports Newtonsoft.Json.Linq
Second Add Reference > Newtonsoft.Json.dll
And Third use this code
Dim request As HttpWebRequest
Dim response As HttpWebResponse = Nothing
Dim reader As StreamReader
request = DirectCast(WebRequest.Create("replace with your WEB LINK, HttpWebRequest)
response = DirectCast(request.GetResponse(), HttpWebResponse)
reader = New StreamReader(response.GetResponseStream())
Dim rawresp As String
rawresp = reader.ReadToEnd()
Dim jResults As JObject = JObject.Parse(rawresp)
'===============LABELS TEXT===========================
Label1.Text = jResults(" replace with your token ").ToString()
And Last One,Replace with your informations