Newtonsoft json exception - json

I am currently making a program that parses the Urban Dictionary API but I cannot get it to return the selected definition.
This is my current code fore retrieving and parsing the data:
Dim sourceString As String = New System.Net.WebClient().DownloadString("http://api.urbandictionary.com/v0/define?term=" & strRet)
rtxtDefinition.Text = sourceString
Dim jResults As JArray = JArray.Parse(sourceString)
Dim results As List(Of JToken) = jResults.Children().ToList()
For Each item As JProperty In results
item.CreateReader()
MsgBox(item.Value("definition"))
Next
note that strRet is the users input
this is an example of the urban dictionary API structure: http://pastebin.com/11Z5uVRN
The current code does not have support to find the (n)th definition only because I first need to get it to return a definition.
So obviously I am doing something wrong because of the error: Newtonsoft.Json.JsonReaderException but I am not sure.
Any help would be amazing. Thanks!
EDIT:

Root of json string you're dealing with is not an array but single object. Therefore, you can parse it to JObject instead of JArray, for example :
Dim jobj As JObject = JObject.Parse(sourceString);
Dim arr As JArray = jobj("list");
For Each(var item in arr.Children(Of JObject)())
MsgBox(item("definition").ToString());
Next

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)

JSON.net combine 2 list(Of JObject) together

Heyy all I am trying to combine 2 JObject lists. I have 2 list(Of JObject) named masterJsonList.Add(jsonWriter.Token) and masterJsonListNA.Add(jsonWriter.Token).
I have not found anything when searching Google that shows me how to combine JObects masterJsonListNA to masterJsonList.
When I try:
masterJsonList.Add(masterJsonListNA) '<-- error here
Dim finalJson As String = JsonConvert.SerializeObject(masterJsonList, Formatting.Indented)
It gives an error of:
Error BC30311 Value of type 'List(Of JObject)' cannot be converted to 'JObject'.
I have even tried the following with no luck as well:
masterJsonList.Concat(masterJsonListNA)
Dim finalJson As String = JsonConvert.SerializeObject(masterJsonList, Formatting.Indented)
Although there is no error using Concat, I only get the masterJsonList values in finalJson and not both masterJsonList & masterJsonListNA.
masterJsonList.Union(masterJsonListNA)
Dim finalJson As String = JsonConvert.SerializeObject(masterJsonList, Formatting.Indented)
And again using Union there is no error, but I also again only get the masterJsonList values in finalJson and not both masterJsonList & masterJsonListNA.
I know it works if I do this:
Dim combinedJsons As Object = masterJsonList.Concat(masterJsonListNA)
Dim finalJson As String = JsonConvert.SerializeObject(combinedJsons, Formatting.Indented)
But I would like to know if that's the correct way of doing this?
Yes. Your final guess is correct. The extension methods Concat, Union, etc. don't operate on the object they're invoked on. Instead they return new object containing the result of the operation. You actually don't need to us As clause for the combinedList - let the compiler to infer it, like so:
Dim combinedJsons = masterJsonList.Concat(masterJsonListNA)
But if you don't need the combinedJsons for anything else you can Concat the lists in place of the first parameter to SerializeObject:
Dim finalJson = JsonConvert.SerializeObject(masterJsonList.Concat(masterJsonListNA), Formatting.Indented)
On the other hand, the List<T>.Add() method do work on the instance it is invoked on, BUT it adds objects of type T, not whole lists of type T.

Parse JSON Children to objects

I am attempting to parse JSON children values to objects in vb.net. The below code I have been able to get first set of children objects, but I am unable to go any deeper. When it reaches subitem2 it gives me An unhandled exception of type 'System.NullReferenceException' occurred.
Dim o As JObject = JObject.Parse(jsonstring)
Dim results As List(Of JToken) = o.Children().ToList
For Each item As JProperty In results
item.CreateReader()
Dim strfname As String
Dim strlname As String
Dim strphone As String
For Each subitem As JObject In item.Value
strfname = subitem("firstname")
strlname = subitem("lastname")
strphone = subitem("Phone")
For Each subitem2 As JObject In subitem("Deposits")
Dim id As String
Dim amount As String
id = subitem("id")
amount = subitem("amount")
Next
Next
Next
I know it is months after the event, but I was just looking for some Json parsing examples and stumbled across this. In your code I notice that the two lines:
id = subitem("id")
amount = subitem("amount")
look wrong - should they not be:
id = subitem2("id")
amount = subitem2("amount")
apologies if I am way off, but thought I would point out what I thought was the error.
I was unable to find a sufficient method to do this is directly in JSON. I converted the JSON String and did it in XML. I know this isn't the most efficient way but I have a few deadlines to meet. We will be fixing later on.
Replace:
For Each subitem2 As JObject In subitem("Deposits")
Dim id As String
Dim amount As String
id = subitem("id")
amount = subitem("amount")
Next
with :
Dim id As String = ""
Dim subitem2 As List(Of JToken) = subitem("device").ToList
For Each Citem As JProperty In subitem2
Citem.CreateReader()
Select Case Citem.Name
Case "id"
id = Citem.Value
End Select
Next

Json.NET convert linq result into IEnumerable<JObject>

I have a LINQ object that needs to be converted into IEnumerable JObject
The following JavaScriptSerializer is working fine in that I can see the json data from the LINQ object.
Dim serializer As New JavaScriptSerializer()
Dim serializedResult = serializer.Serialize(results)
I need to do something similar with the JSON.NET but I have tried...
Dim jobject = New JObject(results)
Dim jarray = New JArray(results)
both have the following error. "Could not determine JSON object type for type Services.Models.Log"
I have tried this
Dim jobject = JObject.FromObject(results)
with the following error. "Object serialized to Array. JObject instance expected."
The only code that seems to work is this.
Dim jtoken = JToken.FromObject(results)
but how to I turn the JToken back into a JObject so that I can return it as IEnumerable?
How about this way :
Dim jobjects As IEnumerable(Of JObject) =
results.Select(Function(x) JObject.FromObject(x))