Collect All appID's from a JSON file - json

My question is about a JSON file, of which I'm getting errors when putting certain values in a text component.
{
"response": {
"game_count": 4,
"games": [
{
"appid": 10,
"playtime_forever": 0
},
{
"appid": 20,
"playtime_forever": 0
},
{
"appid": 30,
"playtime_forever": 0
},
{
"appid": 40,
"playtime_forever": 0
}
]
}
}
I'm trying to get the values "10,20,30,40" from "appid" in a RichTextBox, one below the other. For this, I am using this code:
JsonString = file
Dim jsonObject As JObject = JObject.Parse(JsonString)
Dim JsonArray As JArray = JArray.Parse(jsonObject.SelectToken("games").ToString)
For Each item As JObject In JsonArray
RichTextBox2.Text = item.SelectToken("appid").ToString
Next
But I'm getting the following error in line 4 of the above code:
Object reference not set to an instance of an object
Is there a way to fix this? I believe my code is right. I'm using the NewtonSoft library.

You can use SelectTokens("..appid") to recursively descent the JSON token hierarchy and find values of properties named "appid", where ".." is the JSONPath recursive descent operator:
Dim jsonObject As JToken = JToken.Parse(JsonString)
Dim appids = jsonObject _
.SelectTokens("..appid") _
.Select(Function(t) CType(t, Long)) _
.ToList()
After finding all "appid" values I cast then to Long using an explicit conversion cast. You could cast to Int If you are certain that all appid values will be less than Int.MaxValue. Or you could cast then to String if you're not interested in the numeric values.
Working .Net fiddle.

Related

How to add JObjects to a JArray when serializing a DataTable to JSON using custom formatting rules?

When attempting to serialize a DataTable to JSON using a custom format, I have some trouble adding JObjects (representing a row) to my JArray (representing the table).
So what I hope to make the table look like is something like this:
[
"Orderline" : {"Item": "Table", "Quantity": "5", "Amount": "50$"},
"Orderline" : {"Item": "Chair", "Quantity": "20", "Amount": "30$"},
"Orderline" : {"Item": "Couch", "Quantity": "2", "Amount": "500$"}
]
I have tried using the Add method to the JArray but I cannot seem to get it to work properly.
At the beginning I have set the JArray to new JArray, so that it is in memory and then I will go along and add the JObjects to it one at a time.
I can see that the add method takes two arguments (Item as JToken and content as object) which makes me a little confused because I do not see anyone else addressing both arguments in other code snippets I have seen online.
JArray is a instance of class Newtonsoft.Json.Linq.JArray.
Desired JObject output:
{
"Orderlines": {
"Item": "Table",
"Quantity": "5",
"Amount": "50"
}
}
Draft code:
Dim JsonObejct as JObject
Dim MyArray as Jarray
Dim Table as datatable
Set MyArray = new JArray
for each row in table
JsonObject = Jobject.FromObject(
New With {
Key.Orderlines = New With{
key.Item = row("Item").Tostring,
key.Quantity = row("Quantity").tostring,
key.Amount = row("Amount").tostring
}
}
)
Myarray.add(JsonObject)
Next row
I work in UiPath Studio and do not have the code in the same place its separated in multiple activities, so please don't get caught in wrongly defined details in the code, everything works until the add to jarray part.
I use Vb .net in UiPath Studio so I would appreciate a solution on how to add the JObects to my JArray in vb .net.
If you simply need to fix your compilation, the following compiles successfully and generates the required JSON structure:
Public Module DataTableJsonExtensions
Public Function ToSpecificOrderlines(ByVal table As DataTable) As JArray
Dim MyArray as JArray = New JArray
For Each row As DataRow In table.Rows
' Possibly you need to use CultureInfo.InvariantCulture in your ToString calls
Dim JsonObject As JObject = JObject.FromObject(
New With {
Key.Orderlines = New With{
key.Item = row("Item").ToString,
key.Quantity = row("Quantity").ToString,
key.Amount = row("Amount").ToString
}
}
)
MyArray.add(JsonObject)
Next row
Return MyArray
End Function
End Module
And then do
Dim myArray as JArray = DataTableJsonExtensions.ToSpecificOrderlines(table)
Demo fiddle #1 here.
However, it seems preferable to generalize the code to serialize any set of DataTable columns by name, with an optional specified format:
Public Module DataTableJsonExtensions
' Serialize all the columns of the table to an Orderlines array
Public Function ToOrderlines(ByVal table As DataTable) As JArray
Return ToOrderlines(table, table.Columns.Cast(Of DataColumn).Select(Function(c) c.ColumnName).ToArray())
End Function
' Serialize the selected columns of the table to an Orderlines array with the specified culture and formats (if any)
Public Function ToOrderlines(ByVal table As DataTable, ByVal columns() As String, Optional ByVal culture As CultureInfo = Nothing, Optional ByVal formats As IDictionary(Of String, String) = Nothing) As JArray
culture = If (IsNothing(culture), CultureInfo.InvariantCulture, culture)
Dim array as JArray = New JArray
For Each row As DataRow In table.Rows
Dim obj As JObject = new JObject (
new JProperty("Orderlines",
New JObject(columns.Select(Function(c) New JProperty(c, String.Format(culture, If(Not IsNothing(formats) AndAlso formats.ContainsKey(c), formats(c), "{0}"), row(c)))))
)
)
array.add(obj)
Next row
Return array
End Function
End Module
Then, to get the JSON shown at the top of your question, with the $ appended to the "Amount" property's value, do:
Dim formats = New Dictionary(Of String, String) From {{"Amount", "{0}$"}}
Dim myArray as JArray = DataTableJsonExtensions.ToOrderlines(table, {"Item", "Quantity", "Amount"}, Nothing, formats)
If you don't need the formatting after all, you call it as follows:
Dim myArray as JArray = DataTableJsonExtensions.ToOrderlines(table, {"Item", "Quantity", "Amount"})
Notes:
You can use DataTableJsonExtensions.ToOrderlines(table) to serialize all columns of the table to an Orderlines array.
In general serialization should always be performed using the invariant culture so that JSON serialized in one locale (say, the United States) can be deserialized in another locale (say, Europe) which uses a different decimal separator or DateTime format. ToString(), however, formats its values using the current culture. Thus I provided the option for you to specify a formatting culture in case you really want to serialize in CultureInfo.CurrentCulture. Passing Nothing for the culture results in using the invariant culture.
In the JSON shown in the top of your question you append a $ to the Amount column, so I provided an optional dictionary of formats in case you need to add that when serializing.
Demo fiddle #2 here.

Unable to deserialize a JSON array with Json.Net

I have a JSON like this:
[
{
"areas": [
{
"area": "New York",
"isDay": true,
"temp": "14"
},
{
"area": "Washington DC",
"isDay": true,
"temp": "30"
},
{
"area": "Los Angles",
"isDay": false,
"temp": "54"
},
{
"area": "San Diego",
"isDay": true,
"temp": "59"
}
],
"status": true,
"code": 200,
"created_at": "2019/06/18 22:26:34.475",
"request_time": "2019/06/18 22:25:28.306"
}
]
I'm trying to get the value of the the area value on the first/second/third object under the Areas array.
I've tried this code to get the value of the first area of the array, which in this case is "New York".
'Note that 'rawJSON' is a string variable that contains the JSON.
Dim jResults As JObject = JObject.Parse(rawJSON)
Dim naming As String = jResults("areas")("name")
However when I run this, I get and exception:
Newtonsoft.Json.JsonReaderException: 'Error reading JObject from JsonReader. Current JsonReader item is not an object: StartArray. Path '', line 1, position 1.'
I am trying to write a function that imports all 'areas' in each array with their identifier of area (such as New York/Washington DC) into a ListBox (so the ListBox will contain, in order: New York, Washington DC, Los Angles).
How can I do this?
There are a couple of problems here:
Your JSON begins and ends with square brackets, so that means it is an array, not a single object. Since it is an array you need to use JArray.Parse() to parse it instead of JObject.Parse().
Inside your array, there is a single object which contains a property areas along with a few other properties like status and code. The value of the areas property is also an array, as denoted by square brackets. So your code needs to account for both of those arrays by adding the indexes. If you want the first item, that would be index zero.
There is no property called name anywhere in the JSON you posted. Instead, the names of the cities are each in a property called area.
Putting it all together, if you want to get the name New York from this JSON, you would do it like this:
Dim jResults As JArray = JArray.Parse(rawJSON)
Dim name As String = jResults(0)("areas")(0)("area")
Demo: https://dotnetfiddle.net/eAfEsx
If you're trying to get multiple names, then you would need a loop. You could do something like this:
Dim names As New List(Of String)()
For Each area As JObject In jResults(0)("areas")
Dim name As String = area("area")
names.Add(name)
Next
Demo: https://dotnetfiddle.net/BtSa6O
As you can see from the JSON structure you have posted, the JSON starts with a square bracket. That's the start of an array, the StartArray: when the JsonReader starts reading the JSON, the first TokenType is a JsonToken.StartArray (what the error is telling you).
Then there's an Object, defined by the braces: { }.
So you have an Array or List of Objects.
The first property of this object (areas) is of Type Array (or List).
It defines a collection of Objects.
Other properties, (status, code, etc.) have a single value.
[
{
"areas": [ { ... }, { ... } ]
"other": "other value"
}
]
You can parse the outer Array with JArray. The first element in the array (and the only one you're showing here), is the outer array. The first property of the first element in the outer array is the areas Array.
So you could write:
Dim areasArray = JArray.Parse(rawJson)(0)("areas")
Dim firstAreaValue = areasArray(0)("area").ToString()
The value of firstAreaValue is then "New York".
This is can be tiresome and prone to errors. You can generate a class Model from the JSON and use this model to deserialize the JSON to .Net classes, making it easier to handle, use as Source of Data, modify, serialize back etc.
Your JSON is an Array of Objects, so let's build the Root Object as a .Net class:
Note that I've set the Type of the CreatedAt and RequestTime properties to DateTime (Date): the string format of the DateTime, "2019/06/18 22:26:34.475", can be deserialized correctly.
DateTimeOffset is probably better. Your choice.
Public Class AreasRoot
<JsonProperty("areas")>
Public Property Areas As List(Of AreaObject)
<JsonProperty("status")>
Public Property Status As Boolean
<JsonProperty("code")>
Public Property Code As Long
<JsonProperty("created_at")>
Public Property CreatedAt As DateTime
<JsonProperty("request_time")>
Public Property RequestTime As DateTime
End Class
The Areas property is an Array or List of another type of object that contains 3 properties:
Public Class AreaObject
<JsonProperty("area")>
Public Property AreaArea As String
<JsonProperty("isDay")>
Public Property IsDay As Boolean
<JsonProperty("temp")>
Public Property Temp As Long
End Class
To deserialize using this Model, call JsonConvert.DeserializeObject(Of Type)(json).
The Type is, as mentioned, an Array or List(Of RootObject):
Dim areasArray = JsonConvert.DeserializeObject(Of List(Of AreasRoot))(rawJson).First()
Now New York is:
Dim firstArea = areasArray.Areas.First().Area
' Or
Dim firstArea = areasArray.Areas(0).Area
You can list all the Area names with:
For Each areaObj In areasArray.Areas
Console.WriteLine(areaObj.Area)
Next

How to properly build and append a json file from variables

I'm practising programming an application that takes user input and then outputs it to a json file.
I found a how to that explains how to do it. For the sake of length, I'm leaving out the input code and just including the json builder.
ASSIGN
uComp = "testCompany"
uEmail = "testEmail"
uName = "testName"
uAdd = "Additional"
.
DEFINE VARIABLE myObj AS JsonObject NO-UNDO.
DEFINE VARIABLE myData AS JsonObject NO-UNDO.
DEFINE VARIABLE dataParams AS JsonObject NO-UNDO.
DEFINE VARIABLE lResult AS LONGCHAR NO-UNDO
VIEW-AS EDITOR LARGE SIZE 60 BY 16.
DEFINE VARIABLE lJArray AS JsonArray NO-UNDO.
DEFINE VARIABLE lAnotherArray AS JsonArray NO-UNDO.
OUTPUT TO "output path.json".
myObj = NEW JsonObject().
dataParams = NEW JsonObject().
myObj:Add("id", "01").
dataParams:Add("Company_name", uComp).
dataParams:Add("uEmail", uEmail).
dataParams:add("uName", uName).
dataParams:add("AddInfo", uAdd).
lJArray = NEW JsonArray().
lJArray:Add(dataParams).
myObj:Add("data", lJArray).
myObj:Write(lResult, TRUE).
DISPLAY lResult.
That part works fine, but my output is like so:
lResult-----------------------------------------------------
{
"id": "01",
"data": [
{
"Company_name": "testCompany",
"uEmail": "testEmail",
"uName": "testName",
"AddInfo": "Additional"
}
]
}
how do I prevent the
lResult-----------
from being added to the file.
Secondly, I want to add additional information to the file when the code runs again so that the output will become.
{
"id": "01",
"data": [
{
"Company_name": "testCompany",
"uEmail": "testEmail",
"uName": "testName",
"AddInfo": "Additional"
},
{
"Company_name": "testCompany",
"uEmail": "testEmail",
"uName": "testName",
"AddInfo": "Additional"
}
]
}
What is the correct way to target a point in the file and add additional objects?
I though it might be something along the lines of an
append
property.
I would leave the complete JSON I/O to the JSON parser in the language. So instead of the append, I'd read in the file into a JSON object and add the additional objects/properties in memory and write back to a file.
Just an output with append won't produce value JSON. This should work:
FILE-INFORMATION:FILE-NAME = "myfile.json" .
IF FILE-INFORMATION:FULL-PATHNAME > "":U THEN DO:
myObj = CAST ((NEW ObjectModelParser()):ParseFile(FILE-INFORMATION:FULL-PATHNAME),
JsonObject) .
lJArray = myObj:GetJsonArray("data") .
END.
ELSE DO:
myObj = NEW JsonObject().
myObj:Add("id", "01").
lJArray = NEW JsonArray().
myObj:Add("data", lJArray).
END.
dataParams = NEW JsonObject().
dataParams:Add("Company_name", uComp).
dataParams:Add("uEmail", uEmail).
dataParams:add("uName", uName).
dataParams:add("AddInfo", uAdd).
lJArray:Add(dataParams).
myObj:WriteFile("myfile.json", TRUE).
how do I prevent the
lResult-----------
from being added to the file.
I suspect it's because the variable has a VIEW-AS phrase on the definition. But using the JsonObject as an object and calling the WriteFile method is the (far) better approach.

Comparing Json data. Python 3

I have the following Json file and I need to compare data to see how many times each value repeat itself. The problem is, I have no idea about handling Json. I don't want the answer to my exercise, I want to know how to access the data. Json:
{
"tickets": [
{
"ticket_id": 0,
"timestamp": "2016/05/26 04:47:02",
"file_hash": "c9d4e03c5632416f",
"src_ip": "6.19.128.119",
"dst_ip": "145.231.76.44"
},
{
"ticket_id": 1,
"timestamp": "2017/05/28 16:14:22",
"file_hash": "ce8a056490a3fd3c",
"src_ip": "100.139.125.30",
"dst_ip": "145.231.76.44"
},
{
"ticket_id": 2,
"timestamp": "2015/08/23 03:27:10",
"file_hash": "d17f572496f48a11",
"src_ip": "67.153.41.75",
"dst_ip": "239.168.56.243"
},
{
"ticket_id": 3,
"timestamp": "2016/02/26 14:01:33",
"file_hash": "3b28f2abc966a386",
"src_ip": "6.19.128.119",
"dst_ip": "137.164.166.84"
},
]
}
If this is a string representation of the object, first you need to set a variable and parse the string to have object you can work with.
jsonString = "{...your json string...}"
Then parse the string,
import json
jsonObject = json.loads(jsonString)
To access the data within it's like any other js object. Example :
jsonObject.tickets[0].timestamp
would return "2016/05/26 04:47:02"
tickets is the key within the jsonObject, 0 is the index of the first object in the list of tickets.
You can use the built-in "json" library to parse your file into an object:
import json
f = open('myfile.json','r')
tickets = json.loads(f.read())
This will return a "tickets" object. How you "compare" (or what exactly you compare) is up to you.

How can I parse a JSON Array of objects to a list of VB.NET objects?

I installed JSON.Net through NuGet and now I want to parse a json array with objects to a list of objects in VB.NET. I have no idea where to begin.
My JSON array:
[
{
"servername": "US - New Jersey",
"ovpnlocation": "servers/newjersey.ovpn"
},
{
"servername": "The Netherlands",
"ovpnlocation": "servers/nl.ovpn"
},
{
"servername": "Belgium",
"ovpnlocation": "servers/belgium.ovpn"
}
]
I have a list of objects that I want to fill:
Dim ServerList As New List(Of ServerLocation)
And my ServerLocation class contains this:
Public Property ServerName As String
Public Property OVPNLocation As String
Using JSON.Net something like this should work, json being a string holding the JSON you listed above:
Dim ServerList As List(Of ServerLocation) = JsonConvert.DeserializeObject(Of List(Of ServerLocation))(json)