Decode JSON in Visual Basic 2010 Express - arrays

I am just learning the basics in VB 2010, and I am trying to design a program to maintain a database. I have a JSON string in the database that contains a list of image files and their relevant ID numbers. This is in JSON as a website also uses this data.
The example code is
[{"ID": 0, "Path": "Image0.jpg"},{"ID": 1, "Path": "Image1.jpg"}, {"ID": 2, "Path": "Image2.jpg"},{"ID": 3, "Path": "Image3.jpg"}]
I have tried using JSON.NET, but I am a novice and don't know why it isn't working.
I wish for there to be a way I can return the image files, for example in php $DecodedArray[0] would work, I am looking for a way to replicate this in Visual Basic.
Imports System.Web.Script.Serialization
Module Module1
Public Class Target
Public ID, Image As String
End Class
Sub Main()
Console.Clear()
Dim ser As New JavaScriptSerializer()
Dim input As String = My.Computer.FileSystem.ReadAllText("JSONFile.txt")
'[{"ID": 0, "Path": "Image0.jpg"},{"ID": 1, "Path": "Image1.jpg"}, {"ID": 2, "Path": "Image2.jpg"},{"ID": 3, "Path": "Image3.jpg"}]
Console.WriteLine(input)
Console.WriteLine()
Dim output As Target = ser.Deserialize(Of Target)(input)
Console.Write(output.ID.0)
Console.ReadKey()
End Sub
End Module
With this code, I would like the output to be Image0.jpg
Note, I cannot upgrade from Visual Basic 2010 Express

Because your JSON has numeric keys instead of expected keys, it would be difficult to define a custom type to match it. I believe your best bet is to deserialize into a Dictionary(Of String, String) - this will deserialize properly, and you can read through the dictionary to get your items.
So:
Dim output = ser.Deserialize(Of Dictionary(Of String, String))(input)
For Each key As String In output.Keys
Console.WriteLine("{0}: {1}", key, output(key))
Next
Normally when you define a regular type, you'd have to know the names of the JSON properties. Given your Target class, your JSON would actually look like:
[
{ "ID":"0", "Image":"Image0.jpg" },
{ "ID":"1", "Image":"Image1.jpg" },
{ "ID":"2", "Image":"Image2.jpg" }
]
And it would deserialize into an array of Target objects, rather than a single one. But if you're stuck with the JSON that you've got, the Dictionary is the way to go.
If you're able to use the cleaner JSON from here, your code is just about right. You just deserialize into an array instead, and you can access elements of that array. So:
Dim output = ser.Deserialize(Of Target())(input)
For i As Integer = 0 To output.GetUpperBound(0)
Console.WriteLine("{0}: {1}", output(i).ID, output(i).Image)
Next

Related

How to add dictionary values to an Array in VBA instead of reference

I am sending data from Excel to the dashing.io dashboard via JSON.
The data which I am sending consist of several touples of data like
[{"Group":"Interface","progress";"10"},{"Group":"HMI","progress";"20"}]
Right now I am using several dictionary objects progress1, progress2 to hold the data like:
DIM progress1 as new Dictionary
DIM progress2 as new Dictionary
progress1.add "Group", "Interface"
progress1.add "Progress", 10
progress2.add "Group", "HMI"
progress2.add "Progress", 20
And finally for creating the JSON object, the two progress dictionaries are added to one object:
Dim body as new Dictionary
body.add Array(progress1, progress2)
As there are more than just two progress items, I wanted to create a for-loop to add data to a dictionary and then add that dictionary item to an array like
for i=1 to 10
progress.add "Group", Range(i,1)
progress.add "progress", Range (i,2)
next i
overall_progress.add (progress)
It seems that I am adding the object as reference, instead of the values of the object. If the loop runs 10 times, I end up having ten times the same entry.
Any idea how to add the values of a dictionary to an array, instead of the reference?
Creating objects in a loop is easier to manage if you use a "factory" function.
E.g:
Sub Tester()
Dim body As New Collection, i As Long
For i = 1 To 10
body.Add Progress(Cells(i, 1), Cells(i, 2))
Next i
End Sub
Function Progress(grp, prog) As Object
Dim rv As New scripting.dictionary
rv.Add "Group", grp
rv.Add "Progress", prog
Set Progress = rv
End Function

Excel VBA - How to search array and return value?

I have some data that looks like this (starting in A1):
Batman
Carl Reiner
Ford
Sushi
But I have a two dimensional array, storing those names, and their type:
Dim Names()
ReDim Names(4,1)
Names(0,0) = "Batman"
Names(0,1) = "Superhero"
Names(1,0) = "Carl Reiner"
Names(1,1) = "Comedian"
Names(2,0) = "Ford"
Names(2,1) = "Car Manufacturer"
Names(3,0) = "Sushi"
Names(3,1) = "Food"
Now, I would like to loop through column A and replace those data points with their equivalent type. I thought there would be a relatively simple way to essentially search Names(x,0) for "Batman" then just replace it with Names(x,1). What's the best way to do so?
I found somewhere that you could possibly use Vlookup with this, so I tried this, to no avail:
Evaluate(WorksheetFunction.Vlookup("A1",Names,1,False)
With my thought being it would look for "Batman" and return the value in Names in the "1" dimension...But that keeps giving me an error (Type 13 Mismatch).
Thanks for any ideas/help!
edit: I found this post and seem to be getting somewhere with Application.Match("A1",Application.Index(Names,0,1),0) which returns the position of "A1" in the array. Now I just need to return the offset and get the "1" position of that...
Edit 2: I think I got it. Using MATCH to find the position of "A1" then just use the array to find it:
Names(Application.Match("A1",Application.Index(Names,0,1),0),1)
So, when A1 is Batman, it finds that position in the index, then it finds the equivalent return in the second dimension.
(Sorry for the lack of semantics, I don't have a very good idea of how to refer to this, so please let me know if I can clarify).
It seems like this would be easier using a Dictionary.
Sub testing()
Dim dic As Object
Set dic = CreateObject("scripting.dictionary")
With dic
.Add "Batman", "Superhero"
.Add "Carl Reiner", "Comedian"
.Add "Ford", "Car Manufacturer"
End With
MsgBox "Batman is a " & dic.Item("Batman")
End Sub
I think if you want to use worksheet functions, you have to put the data into a worksheet (e.g. a column or pair of columns) instead of an array. This is pretty easy to do, though, and you can use a different worksheet, or even another workbook, and there are solutions to hide these, so your users don't have to see that data cluttering the other worksheets.

VB.Net JavaScriptSerializer Only getting first value of JSON Array

I am currently attempting to Convert some json
{"payload":{"versions":[{"1.0.2":{"vnum":"1.0.2","vloc":"http:\/\/*domainomitted*\/flyswatter\/files\/flyswatter_102.zip"},"1.0.1":{"vnum":"1.0.1","vloc":"http:\/\/*domainomitted*\/flyswatter\/files\/flyswatter_101.zip"}}]}}
Into a Iteratorable Object in VB.Net Here is what I have at the moment but it only returns the first element from the json array:
Dim vNum() As Object = j.getCfg("versions", False)
'Data is sent as versions:["1.0.1":{"vnum": "1.0.1", "vloc": "http://..."}, "1.0.2":{...}]
log("Populating:")
cbVSel.Items.Clear()
MessageBox.Show(vNum.Length) 'Returns 1
For Each ver As Dictionary(Of String, Object) In vNum
Dim k As String = ver.Keys(0)
MessageBox.Show(k.ToString()) 'Returns 1.0.2
Next
I feel like its simple but I have been working on this for a while now. I have also tried different Objects like HashTable, Array, Dictionary.
So In short. How can I get this working; Populating vNum with all the versions from JSON Array
If You need to see the JSON Parsing code let me know. Any Help is very much appreciated.
Thanks!
So I ended up figuring it out. It was as simple as me using JSON wrong I changed the serverside to output:
{"payload":{"versions":[{"vnum":"1.0.2","vloc":"http:\/\/*domainomitted*\/flyswatter\/files\/flyswatter_102.zip"},{"vnum":"1.0.1","vloc":"http:\/\/*domainomitted*\/flyswatter\/files\/flyswatter_101.zip"}]}}
And all was well again. Thanks for your time!

JMeter: How to count JSON objects in an Array using jsonpath

In JMeter I want to check the number of objects in a JSON array, which I receive from the server.
For example, on a certain request I expect an array with 5 objects.
[{...},{...},{...},{...},{...}]
After reading this: count members with jsonpath?, I tried using the following JSON Path Assertion:
JSON Path: $
Expected value: hasSize(5)
Validate against expected value = checked
However, this doesn't seem to work properly. When I actually do receive 5 objects in the array, the response assertion says it doesn't match.
What am I doing wrong?
Or how else can I do this?
Although JSONPath Extractor doesn't provide hasSize function it still can be done.
Given the example JSON from the answer by PMD UBIK-INGENIERIE, you can get matches number on book array in at least 2 ways:
1. Easiest (but fragile) way - using Regular Expression Extractor.
As you can see, there are 4 entries for category like:
{ "category": "reference",
{ \"category\": \"fiction\"
...
If you add a Regular Expression Extractor configured as follows:
It'll capture all the category entries and return matches number as below:
So you will be able to use this ${matches_matchNr} variable wherever required.
This approach is straightforward and easy to implement but it's very vulnerable to any changes in the response format. If you expect that JSON data may change in the foreseeable future continue with the next option.
2. Harder (but more stable) way - calling JsonPath methods from Beanshell PostProcessor
JMeter has a Beanshell scripting extension mechanism which has access to all variables/properties in scope as well as to the underlying JMeter and 3rd-party dependencies APIs. In this case you can call JsonPath library (which is under the hood of JsonPath Extractor) directly from Beanshell PostProcessor.
import com.jayway.jsonpath.Criteria;
import com.jayway.jsonpath.Filter;
import com.jayway.jsonpath.JsonPath;
Object json = new String(data);
List categories = new ArrayList();
categories.add("fiction");
categories.add("reference");
Filter filter = Filter.filter(Criteria.where("category").in(categories));
List books = JsonPath.read(json, "$.store.book[?]", new Filter[] {filter});
vars.put("JSON_ARRAY_SIZE", String.valueOf(books.size()));
The code above evaluates JSONPath expression of $.store.book[?] against parent sampler response, counts matches number and stores it into ${JSON_ARRAY_SIZE} JMeter Variable
which can later be reused in an if clause or an assertion.
References:
JMeter – Working with JSON – Extract JSON response
JMeter's User Manual Regular Expressions entry
JSON Path Documentation and Examples
How to use BeanShell: JMeter's favorite built-in component
This is not possible with the plugin you are using (JMeter-plugins).
But it can be done with JSON Extractor since JMeter 3.0, this plugin has been donated by UbikLoadPack (http://jmeter.apache.org/changes_history.html)
Example:
Say you have this JSON that contains an array of books:
{ "store": {"book": [
{ "category": "reference","author": "Nigel Rees","title": "Sayings of the Century","price": 8.95},
{ "category": "fiction","author": "Evelyn Waugh","title": "Sword of Honour","price": 12.99},
{ "category": "fiction","author": "Herman Melville","title": "Moby Dick","isbn": "0-553-21311-3","price": 8.99},
{ "category": "fiction","author": "J. R. R. Tolkien","title": "The Lord of the Rings","isbn": "0-395-19395-8","price": 22.99}
],
"bicycle": {"color": "red","price": 19.95}} }
To have this count:
1/ Add JSON Extractor:
The count will be then available bookTitle_matchNr which you can access through:
${bookTitle_matchNr}
Running this Test Plan would display this:
As you can see, Debug Sampler-${bookTitle_matchNr} shows Debug Sampler-4

How can I import records from a text file (not delimited) in access db?

I am just trying figure out a record import program from text file into access database using Microsoft.Jet.Oledb Provider 4.0 and Vb.net. And it seems easy but my problem is different. In the text file, records are not delimited. I am a newbie so it became too hard for me. Please give some hint to solve this issue.
Format of the text file:
Field Name & Size
Date[Date,ShortDate]FirstName[20]LastName[20]Sex[1]Age[2]
Records
02062011john……………..little………………M15
…
…
…
Can I put delimiter programmatically while reading the text file using stream reader and later simply import the whole file in DB. Any suggestions
One option is to use the TextFieldParser class:
http://msdn.microsoft.com/en-us/library/microsoft.visualbasic.fileio.textfieldparser.aspx
Imports Microsoft.VisualBasic.FileIO
Private Sub ReadFixedWidthText()
Dim theString As String = "John Little M15" + vbCrLf + "Jane Doe F30"
Using rdr As New StringReader(theString)
Using parser As New TextFieldParser(rdr)
parser.TextFieldType = FieldType.FixedWidth
parser.FieldWidths = New Integer() {20, 20, 1, 2}
parser.TrimWhiteSpace = True
While Not parser.EndOfData
Dim fields() As String = parser.ReadFields()
For i As Integer = 0 To fields.Length - 1
Console.WriteLine("Field {0}: {1}", i, fields(i))
Next
End While
End Using
End Using
End Sub
I used a StringReader in this example, but you could just as easily use a StreamReader or just use the filename in the TextFieldParser constructor.
Or you could use a combination of the StreamReader and the String.Substring method to get the individual fields.
Is it not space delimited? Do you have any constraints on text file like for example from first character till 100th character is first name etc? If yes you can break the text on the basis of those constraints.

Resources