extract element from an array - json

Hi I asked the similar question before: I have a large JSON file but the information I need is only small part of it. However, that part is a two dimensional array from "text"."size" part.Is any way I can loop each array and and get the number from what I have already?
{"widget": { "debug": "on", "window": { "title": "Sample Konfabulator Widget", "name": "main_window", "width": 500, "height": 500 }, "image": { "src": "Images/Sun.png", "name": "sun1", "hOffset": 250, "vOffset": 250, "alignment": "center" }, "text": { "data": "Click Here", "size": [[0,1,2,3,4],[5,6,7,8,9],[10,11,12,13,14]], "style": "bold", "name": "text1", "hOffset": 250, "vOffset": 100, "alignment": "center", "onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;" } } }
I was taught from someone(thank you!) to use the following code
Option Explicit
Public Sub GetInfo()
Dim strJSON As String, json As Object, rowNumber As Long
Application.ScreenUpdating = False
Const PATH As String = "C:\Users\User\Desktop\test.JSON"
strJSON = GetJSONFromFile(PATH)
Set json = JsonConverter.ParseJson(strJSON)
Set json = json("widget")("text")
Dim key As Variant
With ThisWorkbook.Worksheets("Sheet1")
For Each key In json
rowNumber = rowNumber + 1
.Cells(rowNumber, 1) = key
.Cells(rowNumber, 2) = json(key)
Next key
End With
Application.ScreenUpdating = True
End Sub
Many Thanks

Seeing expected output would help. If you are simply after the items within the collection of collections returned by JsonConverter.ParseJson(strJSON)("widget")("text")("size") then the following will empty them.
Option Explicit
Public Sub GetInfo()
Dim strJSON As String, json As Object, rowNumber As Long, i As Long, j As Long
Const PATH As String = "C:\Users\User\Desktop\test.JSON"
strJSON = GetJSONFromFile(PATH)
Set json = JsonConverter.ParseJson(strJSON)("widget")("text")("size") '<collection of collections
With ThisWorkbook.Worksheets("Sheet1")
For i = 1 To json.Count
For j = 1 To json(i).Count
rowNumber = rowNumber + 1
.Cells(rowNumber, 1) = json(i)(j)
Next
Next
End With
End Sub
Public Function GetJSONFromFile(ByVal PATH As String) As String
Dim fso As Object, f As Object, outputString As String
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(PATH)
Do Until f.AtEndOfStream
outputString = f.ReadAll()
Loop
f.Close
GetJSONFromFile = outputString
End Function
JSON structure:
You can see the path down to the collection of collections in the JSON structure below. The {} are dictionaries and the [] are collections.

Related

Public Property Array Setting Values

I am using VB2010 and I want to without error or usigg Try, to check if a public property array index is existent. So, I am deserializing json data that looks like this:
{
"Title": "The Terminator",
"Year": "1984",
"Rated": "R",
"Released": "26 Oct 1984",
"Runtime": "107 min",
"Genre": "Action, Sci-Fi",
"Director": "James Cameron",
"Writer": "James Cameron, Gale Anne Hurd, William Wisher (additional dialogue)",
"Actors": "Arnold Schwarzenegger, Michael Biehn, Linda Hamilton, Paul Winfield",
"Plot": "A seemingly indestructible robot is sent from 2029 to 1984 to assassinate a young waitress, whose unborn son will lead humanity in a war against sentient machines, while a human soldier from the same war is sent to protect her at all costs.",
"Language": "English, Spanish",
"Country": "UK, USA",
"Awards": "6 wins & 6 nominations.",
"Poster": "https://m.media-amazon.com/images/M/MV5BYTViNzMxZjEtZGEwNy00MDNiLWIzNGQtZDY2MjQ1OWViZjFmXkEyXkFqcGdeQXVyNzkwMjQ5NzM#._V1_SX300.jpg",
"Ratings": [
{
"Source": "Internet Movie Database",
"Value": "8.0/10"
},
{
"Source": "Rotten Tomatoes",
"Value": "100%"
},
{
"Source": "Metacritic",
"Value": "84/100"
}
],
"Metascore": "84",
"imdbRating": "8.0",
"imdbVotes": "731,313",
"imdbID": "tt0088247",
"Type": "movie",
"DVD": "03 Sep 1997",
"BoxOffice": "N/A",
"Production": "Orion Pictures Corporation",
"Website": "http://www.terminator1.com/",
"Response": "True"
}
However, not all movies return the "Ratings" array. So, I want to be able to still set the array as Source imdb, rotten tomatoes, and metacritic and those Values as "N/A" if they don't exist. I wish the api would just return it as N/A it would be so much easier.
Here's my class for Ratings:
Public Class Ratings
Public Property Source As String
Public Property Value As String
End Class
Then my other class that returns the other values from the "Search" Array and it returns a good handful of different strings so I'll just skip to where I do ratings..
Public Class Results
Public Property Title As String
Public Property Year As String
'bunch more public property strings...
Public Property Rating As Ratings()
End Class
Now my form on load im just testing it out and of course I get an index out of bounds error if I try to set it manually or read a specific index because if the array isn't there, then the array indexes are non existent.
Imports System.Net
Imports System.Web.Script.Serialization
Dim Site As New WebClient()
Dim JSS As JavascriptSerializer = New JavascriptSerializer()
Dim strData As String = Site.DownloadString("http://www.omdbapi.com/?t=Terma&apikey=apikeygoeshere
Dim Movie As Results = JSS. Deserializs(Of Results) (strData)
And this is where I'm now stuck. I'm not sure what to do here. Any help would be much appreciated.
OK, this is what I did. Sorry, I am new here, and I wanted to just add a comment with my code but it's too long. However, if anyone knows a shorter way of doing this, please let me know.
Dim jss As JavaScriptSerializer = New JavaScriptSerializer()
Dim Site As New WebClient()
Dim strData As String = Site.DownloadString("http://www.omdbapi.com/?t=Terminator&y=1984&apikey=745dfb00")
Dim mvMovie As Results = New Results
mvMovie = jss.Deserialize(Of Results)(strData)
If mvMovie.Response = "True" Then
Dim imdbRatings As Ratings = New Ratings
Dim rtRatings As Ratings = New Ratings
Dim mtRatings As Ratings = New Ratings
Dim imdbSource As String = "Internet Movie Database"
Dim imdbValue As String = "N/A"
Dim rtSource As String = "Rotten Tomatoes"
Dim rtValue As String = "N/A"
Dim mtSource As String = "Metacritic"
Dim mtValue As String = "N/A"
If mvMovie.Ratings.GetUpperBound(0) = -1 Then
Array.Resize(mvMovie.Ratings, 3)
imdbRatings.Source = imdbSource
imdbRatings.Value = imdbValue
mvMovie.Ratings(0) = imdbRatings
rtRatings.Source = rtSource
rtRatings.Value = rtValue
mvMovie.Ratings(1) = rtRatings
mtRatings.Source = mtSource
mtRatings.Value = mtValue
mvMovie.Ratings(2) = mtRatings
ElseIf mvMovie.Ratings.GetUpperBound(0) = 0 Then
Array.Resize(mvMovie.Ratings, 3)
rtRatings.Source = rtSource
rtRatings.Value = rtValue
mvMovie.Ratings(1) = rtRatings
mtRatings.Source = mtSource
mtRatings.Value = mtValue
mvMovie.Ratings(2) = mtRatings
ElseIf mvMovie.Ratings.GetUpperBound(0) = 1 AndAlso mvMovie.Ratings(1).Source = "Rotten Tomatoes" Then
Array.Resize(mvMovie.Ratings, 3)
mtRatings.Source = mtSource
mtRatings.Value = mtValue
mvMovie.Ratings(2) = mtRatings
ElseIf mvMovie.Ratings.GetUpperBound(0) = 1 AndAlso mvMovie.Ratings(1).Source = "Metacritic" Then
Array.Resize(mvMovie.Ratings, 3)
rtRatings.Source = rtSource
rtRatings.Value = rtValue
mvMovie.Ratings(2) = mvMovie.Ratings(1)
mvMovie.Ratings(1) = rtRatings
End If
End If

Write partial data using VBA

I have a large JSON file but the information I need is only a small part of it. Is there any way I can extract the part I want and write to an Excel sheet instead of writing the whole file? Please see the following example. I only want to extract the "text" part
{"widget": {
"debug": "on",
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}
}
If it is a JSON file you can read as follows and empty into sheet
Option Explicit
Public Sub GetInfo()
Dim strJSON As String, json As Object, rowNumber As Long
Application.ScreenUpdating = False
Const PATH As String = "C:\Users\User\Desktop\test.JSON"
strJSON = GetJSONFromFile(PATH)
Set json = JsonConverter.ParseJson(strJSON)
Set json = json("widget")("text")
Dim key As Variant
With ThisWorkbook.Worksheets("Sheet1")
For Each key In json
rowNumber = rowNumber + 1
.Cells(rowNumber, 1) = key
.Cells(rowNumber, 2) = json(key)
Next key
End With
Application.ScreenUpdating = True
End Sub
Public Function GetJSONFromFile(ByVal PATH As String) As String
Dim fso As Object, f As Object, outputString As String
Set fso = CreateObject("Scripting.FileSystemObject")
Set f = fso.OpenTextFile(PATH)
Do Until f.AtEndOfStream
outputString = f.ReadAll()
Loop
f.Close
GetJSONFromFile = outputString
End Function
If you inspect the JSON you can see the the top level dictionary has a key "widget" which gives access to inner dictionaries. One of these has the key "text"; that is the one you are after and can be accessed with the syntax
Set json = json("widget")("text")
You could shorten the sub code at the top to:
Option Explicit
Public Sub GetInfo()
Dim strJSON As String, json As Object, rowNumber As Long
Application.ScreenUpdating = False
Const PATH As String = "C:\Users\HarrisQ\Desktop\test.JSON"
strJSON = GetJSONFromFile(PATH)
Set json = JsonConverter.ParseJson(strJSON)
Set json = json("widget")("text")
With ThisWorkbook.Worksheets("Sheet1")
.Cells(1, 1).Resize(json.Count) = Application.WorksheetFunction.Transpose(json.keys)
.Cells(1, 2).Resize(json.Count) = Application.WorksheetFunction.Transpose(json.Items)
End With
Application.ScreenUpdating = True
End Sub

Why sub json contains backslashes

I need To Build json of the following structure:
[{
Id: M1
Name: Menu1
Checked: True
Children:[
{Id: I1 , Name: Item1 , Checked: true, view:true , write:true},
{Id: I2 , Name: Item2 , Checked: true, view:true , write:true},
.. etc
]
},
{
Id: M2
Name: Menu2
Checked: True
Children:[
{Id: I1 , Name: Item1 , Checked: true, view:true , write:true},
{Id: I2 , Name: Item2 , Checked: true, view:true , write:true},
.. etc
]
} , etc..
]
I'm Using Vb.Net , SQl Server To get the menus and Items (objects) from the database and convert the data to json string using this code:
'Get Menus
Dim menus = DataFactory.Instance.GetMenusAndObjects(connectionString)
'Create JSON String
Dim jsonSerializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer()
Dim json As String = "["
For Each m In menus
Dim children As String = "["
Dim menu_checked As Boolean = True
For Each obj In m.Objects
Dim checked As Boolean = True
Dim view As Boolean = True
Dim write As Boolean = True
Dim link = DataFactory.Instance.GetProfileObjectLink(connectionString, profile_code, obj.ObjectCode)
If IsNothing(link) Then
view = False
write = False
checked = False
menu_checked = False
Else
If link.AllowToView.Equals("N") Then
view = False
menu_checked = False
End If
If link.AllowToModify.Equals("N") Then
write = False
menu_checked = False
End If
End If
children &= jsonSerializer.Serialize(New With {Key .Id = obj.ObjectCode,
.Name = obj.ObjectDesc,
.Checked = checked,
.View = view,
.Write = write}) & ","
Next
children &= "]"
json &= jsonSerializer.Serialize(New With {Key .Id = m.MenuCode,
.Name = m.MenuName,
.Checked = menu_checked,
.Children = children}) & ","
Next
If json.Length > 1 Then
json = json.Substring(0, json.Length - 1)
End If
json &= "]"
A Sample of the Resulted Json string in vb.Net:
[{"Id":"APPLN","Name":"Application","Checked":false,"Children":"
[{\"Id\":\"CUSTOMER_SCR\",\"Name\":\"62- Clients/
Customers\",\"Checked\":true,\"View\":false,\"Write\":false},
{\"Id\":\"EMP_SCR\",\"Name\":\"10- Employee
Manager\",\"Checked\":true,\"View\":true,\"Write\":true},]"}
,]"}
Why Backslashes are added only to the json on 'Children' Property? Do you think that the double Serialization for the children parameter is causing the problem? and if that's is the real reason how can I concatenate children jsons to the main json strings?
I pushed Each Children into a List Of Object then I converted the list to Array after that I serialized the main json, The Code:
Imports System.Web
Imports System.Web.Services
Imports System.Web.Script.Serialization
Public Class GetMenusAndObjects
Implements System.Web.IHttpHandler
Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest
context.Response.ContentType = "text/plain"
'Get parameters
Dim profile_code = context.Request("profile_code")
Dim connectionString As String = UserIdentity.ClientConfig.ConnectionString
'Get Profiles
Dim menus = DataFactory.Instance.GetMenusAndObjects(connectionString)
'Create JSON String
Dim jsonSerializer As System.Web.Script.Serialization.JavaScriptSerializer = New System.Web.Script.Serialization.JavaScriptSerializer()
Dim json As String = "["
For Each m In menus
' Dim children As String = "["
Dim children = New List(Of Object)
Dim menu_checked As Boolean = True
For Each obj In m.Objects
Dim checked As Boolean = True
Dim view As Boolean = True
Dim write As Boolean = True
Dim link = DataFactory.Instance.GetProfileObjectLink(connectionString, profile_code, obj.ObjectCode)
If IsNothing(link) Then
view = False
write = False
checked = False
menu_checked = False
Else
If link.AllowToView.Equals("N") Then
view = False
menu_checked = False
End If
If link.AllowToModify.Equals("N") Then
write = False
menu_checked = False
End If
End If
children.Add(New With {.Id = obj.ObjectCode,
.Name = obj.ObjectDesc,
.Checked = checked,
.View = view,
.Write = write
})
'children &= jsonSerializer.Serialize(New With {Key .Id = obj.ObjectCode,
' .Name = obj.ObjectDesc,
' .Checked = checked,
' .View = view,
' .Write = write}) & ","
Next
'children &= "]"
json &= jsonSerializer.Serialize(New With {Key .Id = m.MenuCode,
.Name = m.MenuName,
.Checked = menu_checked,
.Children = children.ToArray()}) & ","
Next
If json.Length > 1 Then
json = json.Substring(0, json.Length - 1)
End If
json &= "]"
'Return JSON in response
context.Response.Write(json)
End Sub
ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
Get
Return False
End Get
End Property
End Class

JSON.net string json into object

Hey all I am having difficultys in making this string JSON that I have into an object so that I can use it like this:
json("go")("to")("needed")("spot").toString
and get my value.
Currently the XML to JSON looks like this:
{
"?xml": {
"#version": "1.0",
"#encoding": "UTF-8"
},
"data": {
"recordCount": "1",
"metadata": {
"elementType": [
{
"name": "F_Paragraphtext",
"uiType": "textArea",
"dataType": "string",
"label": "Text String",
"dataLabel": ""
}
]
},
"records": {
"F_Form1": {
"#application_uid": "2a667c59-225c-4954-8e04-77bb083e5180",
"#uid": "61f876f4-9760-4013-85bb-37965cff1fb6",
"F_SingleLine": "test",
"F_Paragraphtext": "{\"Data\":{\"DevisionName\":\"testing service after added field\",\"DevisionCode\":\"test\",\"CodeInString\":\"test^test|4/15/2015|50%|test^test|4/15/2015|25%|test^test|4/23/2015|50%~test^test|4/23/2015|N/A|test^test|4/8/2015|N/A|test^test|3/31/2015|N/A~test^test|4/10/2015|N/A|test^test|5/1/2015|50%|test^test|4/18/2015|N/A~test^test|3/30/2015|50%|test^test|4/24/2015|50%|test^test|5/9/2015|100%~test^test|3/30/2015|25%|test^test|3/30/2015|100%|test^test|4/11/2015|75%\"}}"
}
}
}
}
And I am trying to get the value for F_Paragraphtext, #application_uid & #uid.
The VB.net code I have:
Dim doc1 As XmlDocument = New XmlDocument()
doc.LoadXml(serverResponse)
Dim json1 As String = Newtonsoft.Json.JsonConvert.SerializeXmlNode(doc, Newtonsoft.Json.Formatting.Indented)
jsreader = New Newtonsoft.Json.JsonTextReader(New StringReader(json1))
Try
json = DirectCast(New Newtonsoft.Json.JsonSerializer().Deserialize(jsreader), Newtonsoft.Json.Linq.JObject)
Catch ex As Exception
MsgBox(ex.Message)
End Try
For Each Row In json("data")("records")(febFormID)
Try
dName = json("#application_uid").ToString
Catch ex As Exception
MsgBox(ex.Message)
End Try
Next
While Row value is:
{"#application_uid": "2a667c59-225c-4954-8e04-77bb083e5180"}
The error falls on the dName = Row("#application_uid").ToString. The error is Object reference not set to an instance of an object..
Not quite sure what all I am missing in order to be able to retrieve the Row values but apparently its something....
...making this string JSON that I have into an object so that I can use it like this:
json("go")("to")("needed")("spot").toString
I am trying to get the value for F_Paragraphtext, #application_uid & #uid.
Dim jstr As String = File.ReadAllText(filename)
Dim myJ = JObject.Parse(jstr)
Console.WriteLine("{0} == {1}", "F_Paragraphtext",
myJ("data")("records")("F_Form1")("F_Paragraphtext"))
Console.WriteLine("{0} == {1}", "#application_uid",
myJ("data")("records")("F_Form1")("#application_uid"))
Console.WriteLine("{0} == {1}", "#uid",
myJ("data")("records")("F_Form1")("#uid"))
Output:
F_Paragraphtext == {"Data":{"DevisionName":"testing service after added field","DevisionCode":"test","CodeInString":"test^test|4/15/2015|50%|test^test|4/15/2015|25%|test^test|4/23/2015|50%~test^test|4/23/2015|N/A|test^test|4/8/2015|N/A|test^test|3/31/2015|N/A~test^test|4/10/2015|N/A|test^test|5/1/2015|50%|test^test|4/18/2015|N/A~test^test|3/30/2015|50%|test^test|4/24/2015|50%|test^test|5/9/2015|100%~test^test|3/30/2015|25%|test^test|3/30/2015|100%|test^test|4/11/2015|75%"}}
#application_uid == 2a667c59-225c-4954-8e04-77bb083e5180
#uid == 61f876f4-9760-4013-85bb-37965cff1fb6

Parsing Json using Vb.net Json.NET

Hey all I am getting the following error at random spots in my code:
Object reference not set to an instance of an object.
I know why I am getting it. It does not find the correct property that I have it looking for and therefore it gives the error. Some may have that property and some, as this error shows, may not.
What can I do in order to check first to make sure it has that property? Currently I just have a Try/catch method in place so it can keep going if it does find something that's not there.
For Each Row In json("data")
Try
thePostID = DirectCast(Row("id").ToString(), String)
thePostType = DirectCast(Row("type").ToString(), String)
thePosterID = DirectCast(Row("from")("id").ToString(), String)
thePosterName = DirectCast(Row("from")("name").ToString(), String)
Catch ex As NullReferenceException
msgbox("Did not find that particular property!")
End Try
Next
update
{
"data": [
{
"id": "102zzz533zz_10z52zz9zzzz94z3",
"from": {
"id": "102zzzzz95zzz7",
"name": "Jim zzzzz"
},
"likes": {
"data": [
{
"id": "85zzzzz35zzzz0",
"name": "Anna zzzzz"
},
{
"id": "10zzzz93z31zzzzz",
"name": "Vanessa zzzz zzzz"
},
{
"id": "1zzz44zzz48731z6",
"name": "Leta zzzzzz"
}
],
"paging": {
"cursors": {
"after": "MTAyMdfasdfwrtMTkyNg=",
"before": "ODUasdfasrU5Mwerw"
}
}
}
etc...
This JSON above follows in the same data path as all the others.
Using #Andrews code below:
thePostLikes = NullSafeSelect(Row, "likes.data.id")
If thePostLikes <> "NA" Then
For Each Row2 In json("likes")("data")
thePostLikesID += NullSafeSelect(Row2, "id") & ","
thePostLikesName += NullSafeSelect(Row2, "name") & ","
Next
End If
The value of thePostLikes is always Nothing
There may be a more graceful way to do this that's built in to JSON.NET, but here's a helper function that will just return Nothing if the path you supply doesn't exist:
Function NullSafeSelect(ByVal obj As JToken, ByVal path As String) As String
Dim result As String = Nothing
Dim value As JToken = obj.SelectToken(path, False)
if (value IsNot Nothing)
result = value.ToString()
End If
Return value
End Function
You would call it from your loop like this:
For Each row in json("data")
Dim thePostID As String = NullSafeSelect(row, "id")
Dim thePostType As String = NullSafeSelect(row, "type")
Dim thePosterId As String = NullSafeSelect(row, "from.id")
' ... etc
Next
Note that you do not need the DirectCast because the return type of the function is already String.