This question already has an answer here:
Looping though JSON classic ASP
(1 answer)
Closed 10 months ago.
I try to get value out from model_category and others like this in the JSON file.
I use aspJSON1.19.asp and my setup is:
For Each X In oJSON.data("result")
Set this = oJSON.data("result").item(X)
For Each item in this
Response.Write item & " : " & this.item(item) & "<br>"
Next
Next
But I can't get values from items like model_category.
My JSON file contains:
{
"result": [{
"parent": "",
"skip_sync": "false",
"residual_date": "",
"residual": "0",
"sys_updated_on": "2022-04-08 07:41:11",
"request_line": "",
"sys_updated_by": "jan",
"due_in": "",
"model_category": {
"link": "https://hest.service-now.com/api/now/table/cmdb_model_category/57d5bc14c3031000b959fd251eba8fd7",
"value": "57d5bc14c3031000b959fd251eba8fd7"
},
"sys_created_on": "2021-09-28 13:31:33",
"sys_domain": {
"link": "https://hest.service-now.com/api/now/table/sys_user_group/global",
"value": "global"
},
"u_owned_by_company": {
"link": "https://hest.service-now.com/api/now/table/core_company/bff4eaf51b30201075fb7b75464bcb70",
"value": "bff4eaf51b30201075fb7b75464bcb70"
},
"disposal_reason": "",
"model": {
"link": "https://hest.service-now.com/api/now/table/cmdb_model/6a6b3f731bb72050287b7d55464bcb99",
"value": "6a6b3f731bb72050287b7d55464bcb99"
},
"u_correlation_id": "",
"u_scanned_serial_number": "93619031",
"install_date": "",
"gl_account": "",
"invoice_number": "",
"sys_created_by": "manth",
"warranty_expiration": "",
"asset_tag": "",
"depreciated_amount": "0",
"substatus": "available",
"pre_allocated": "false",
"owned_by": "",
"checked_out": "",
"display_name": "Eizo - EV2456",
"sys_domain_path": "/",
"asset_function": "",
"delivery_date": "4010-04-15 12:25:00",
"retirement_date": "",
"beneficiary": "",
"install_status": "6",
"cost_center": "",
"supported_by": "",
"assigned": "",
"purchase_date": "",
"work_notes": "",
"managed_by": "",
"sys_class_name": "alm_hardware",
"sys_id": "01beedbe1bf6f410d37d8735464bcb50",
"po_number": "6202",
"stockroom": {
"link": "https://hest.service-now.com/api/now/table/alm_stockroom/82fd1e941b8fec108d685532604bcba2",
"value": "82fd1e941b8fec108d685532604bcba2"
},
"checked_in": "",
"u_ritm_reference": {
"link": "https://hest.service-now.com/api/now/table/sc_req_item/c7561ab41b72f41075fb7b75464bcb09",
"value": "c7561ab41b72f41075fb7b75464bcb09"
},
"resale_price": "0",
"vendor": "",
"company": "",
"retired": "",
"justification": "",
"department": "",
"expenditure_type": "",
"assigned_to": "",
"depreciation_date": "",
"old_status": "",
"comments": "",
"cost": "0",
"quantity": "1",
"acquisition_method": "",
"sys_mod_count": "5",
"old_substatus": "",
"serial_number": "6677",
"sys_tags": "",
"u_warranty_start": "",
"order_date": "",
"support_group": "",
"reserved_for": "",
"due": "",
"location": {
"link": "https://hest.service-now.com/api/now/table/cmn_location/ef8b8b9b1b20b050287b7d55464bcbbf",
"value": "ef8b8b9b1b20b050287b7d55464bcbbf"
},
"lease_id": "",
"salvage_value": "0"
}]
}
Any help?
That's because model_category is an object (a Scripting.Dictionary), and you can't Response.Write objects directly - you would have to write another For Each loop.
Use a recursive function instead:
Sub PrintJson(item)
Dim key
If IsObject(item) Then
If item Is Nothing Then Exit Sub
If item.Count = 0 Then Exit Sub
Response.Write "<ul class=""jsonObject"">" & vbLf
For Each key In item
Response.Write "<li>" & vbLf
Response.Write Server.HTMLEncode(key) & " : "
PrintJson item(key)
Response.Write "</li>" & vbLf
Next
Response.Write "</ul>" & vbLf
ElseIf IsArray(item) Then
If UBound(item) < 0 Then Exit Sub
Response.Write "<ul class=""jsonArray"">" & vbLf
For key = 0 To UBound(item)
Response.Write "<li>" & vbLf
Response.Write Server.HTMLEncode(key) & " : "
PrintJson item(key)
Response.Write "</li>" & vbLf
Next
Response.Write "</ul>" & vbLf
ElseIf IsNull(item) Then
Response.Write "<span class=""jsonValue""><i>null</i></span>"
Else
Response.Write "<span class=""jsonValue"">"
Response.Write Server.HTMLEncode(item)
Response.Write "</span>"
End If
End Sub
Now you can do this:
Set oXMLHTTP = CreateObject("MSXML2.XMLHTTP.3.0")
oXMLHTTP.Open "GET", "https://....", False
oXMLHTTP.Send
Set oJSON = New aspJSON
oJSON.loadJSON(oXMLHTTP.responseText)
PrintJson oJSON.data
and it will print any nesting level. This is meant as a helper to visualize the content of e.g. a response from an API.
If you know the exact path to an item, and you know that this item exists (!), you can do access it directly
oJSON("result")(0)("model_category")("value")
But this will result in in an error if any of the keys do not exist on the object.
I am trying to convert the excel data into below JSON format but my code is not converting this is in accurate format. You help will be much appreciated.
There is extra [ in the format how to achieve this with Excel VBA.
The Excel Data
ExcelData
Required JSON Format
JSON Format
My code
Public Function ToJSON(rng As Range) As String
' Make sure there are two columns in the range
If rng.Columns.Count < 2 Then
ToJSON = CVErr(xlErrNA)
Exit Function
End If
Dim dataLoop, headerLoop As Long
' Get the first row of the range as a header range
Dim headerRange As Range: Set headerRange = Range(rng.Rows(1).Address)
' We need to know how many columns are there
Dim colCount As Long: colCount = headerRange.Columns.Count
Dim json As String: json = "["
For dataLoop = 1 To rng.Rows.Count
' Skip the first row as it's been used as a header
If dataLoop > 1 Then
' Start data row
Dim rowJson As String: rowJson = "{"
' Loop through each column and combine with the header
For headerLoop = 1 To colCount
rowJson = rowJson & """" & headerRange.Value2(1, headerLoop) & """" & ":"
rowJson = rowJson & """" & rng.Value2(dataLoop, headerLoop) & """"
rowJson = rowJson & ","
Next headerLoop
' Strip out the last comma
rowJson = Left(rowJson, Len(rowJson) - 1)
' End data row
json = json & rowJson & "},"
End If
Next
' Strip out the last comma
json = Left(json, Len(json) - 1)
json = json & "]"
ToJSON = json
End Function
If you want to arrange the text in json structure manner, you can use vbTab and vbLf:
Public Function ToJSON(rng As Range) As String
' Make sure there are two columns in the range
If rng.Columns.Count < 2 Then
ToJSON = CVErr(xlErrNA)
Exit Function
End If
Dim dataLoop, headerLoop As Long
' Get the first row of the range as a header range
Dim headerRange As Range: Set headerRange = rng.Rows(1).Cells
' We need to know how many columns are there
Dim colCount As Long: colCount = headerRange.Columns.Count
Dim json As String: json = "["
For dataLoop = 1 To rng.Rows.Count
' Skip the first row as it's been used as a header
If dataLoop > 1 Then
' Start data row
Dim rowJson As String: rowJson = vbLf & vbTab & "{" & vbLf
' Loop through each column and combine with the header
For headerLoop = 1 To colCount
rowJson = rowJson & vbTab & vbTab & """" & headerRange.Value2(1, headerLoop) & """" & ":"
rowJson = rowJson & """" & rng.Value2(dataLoop, headerLoop) & """"
rowJson = rowJson & "," & vbLf
Next headerLoop
' Strip out the last comma
rowJson = Left(rowJson, Len(rowJson) - 2) & vbLf
' End data row
json = json & rowJson & vbTab & "},"
End If
Next
' Strip out the last comma
json = Left(json, Len(json) - 1)
json = json & vbLf & "]"
ToJSON = json
End Function
Sub test1()
Debug.Print ToJSON(Range("A1").CurrentRegion)
End Sub
Output:
[
{
"name":"About the inspection",
"questionText":"report name",
"questionHelp":"some help 1",
"sortOrder":"1",
"isActive":"TRUE",
"questionType":"TEXT",
"options":""
},
{
"name":"",
"questionText":"surveyor",
"questionHelp":"some help 2",
"sortOrder":"2",
"isActive":"TRUE",
"questionType":"TEXT",
"options":""
},
... and so on
Public Function ToJSON(rng As Range) As String
' Make sure there are two columns in the range
If rng.Columns.Count < 2 Then
ToJSON = CVErr(xlErrNA)
Exit Function
End If
Dim ar, r As Long, c As Long
Dim json As String, json1 As String
ar = rng.Value2
' Skip the first row as it's been used as a header
For r = 2 To UBound(ar)
If Len(ar(r, 1)) > 0 Then
' close off previous name
If Len(json) > 0 Then
' Strip out the last comma
json = Left(json, Len(json) - 1)
json = json & vbCrLf & "]},"
End If
' start new name
json = json & vbCrLf & "{ ""name"" : """ & ar(r, 1) & """," & vbCrLf & _
"""surveyQuestions"": ["
End If
If Len(ar(r, 2)) > 0 Then
' build column data json
json1 = ""
For c = 2 To UBound(ar, 2)
If Len(json1) > 0 Then json1 = json1 & "," & vbCrLf
json1 = json1 & " """ & ar(1, c) & """:""" & ar(r, c) & """"
Next
' add into json
json = json & vbCrLf & "{" & json1 & vbCrLf & "},"
End If
Next
' Strip out the last comma
json = Left(json, Len(json) - 1)
ToJSON = "{" & vbCrLf & """sections"": [" _
& json & "]}]" & vbCrLf & "}"
End Function
Since you only provided data for the 1st set of JSON format (the 2nd set of format looks weird anyway, are you sure that's correct?), below code only cater for the 1st set of JSON format:
Public Function ToJSON(rng As Range) As String
' Make sure there are two columns in the range
If rng.Columns.Count < 2 Then
ToJSON = CVErr(xlErrNA)
Exit Function
End If
Const rootKey As String = "sections"
Const surveyKey As String = "surveyQuestions"
Dim rngArr As Variant
rngArr = rng.Value2
Dim JSONStr As String
Dim JSONSurvey As String
Dim i As Long
' Skip the first row as it's been used as a header
For i = 2 To UBound(rngArr, 1)
If rngArr(i, 1) <> vbNullString Or rngArr(i, 2) <> vbNullString Then
If rngArr(i, 1) <> vbNullString Then
Dim currentName As String
If rngArr(i, 1) <> currentName Then
If currentName <> vbNullString Then
currentName = rngArr(i, 1)
JSONStr = JSONStr & JSONSurvey & "]},{" & KeyValue(rngArr(1, 1), rngArr(i, 1)) & "," & Chr(34) & surveyKey & Chr(34) & ": ["
JSONSurvey = vbNullString
Else
currentName = rngArr(i, 1)
JSONStr = JSONStr & "{" & KeyValue(rngArr(1, 1), rngArr(i, 1)) & "," & Chr(34) & surveyKey & Chr(34) & ": ["
End If
Else
End If
Else
JSONSurvey = JSONSurvey & ","
End If
Dim n As Long
For n = 2 To UBound(rngArr, 2)
If n = 2 Then JSONSurvey = JSONSurvey & "{"
Select Case n
Case 4, 5: JSONSurvey = JSONSurvey & KeyValue(rngArr(1, n), rngArr(i, n), False)
Case Else: JSONSurvey = JSONSurvey & KeyValue(rngArr(1, n), rngArr(i, n))
End Select
If n <> UBound(rngArr, 2) Then
JSONSurvey = JSONSurvey & ","
Else
JSONSurvey = JSONSurvey & "}"
End If
Next n
End If
Next
JSONStr = JSONStr & JSONSurvey & "]}"
' Strip out the last comma
JSONStr = Left(JSONStr, Len(JSONStr) - 1)
ToJSON = "{" & Chr(34) & rootKey & Chr(34) & ": [" & _
JSONStr & _
"}]}"
End Function
Private Function KeyValue(argKey As Variant, argValue As Variant, Optional ValueAsText As Boolean = True) As String
If ValueAsText Then
KeyValue = Chr(34) & argKey & Chr(34) & ":" & Chr(34) & argValue & Chr(34)
Else
KeyValue = Chr(34) & argKey & Chr(34) & ":" & LCase(argValue)
End If
End Function
Running this to Range("A1:G23") which is your entire data will produce this:
{"sections": [{"name":"About the inspection","surveyQuestions": [{"questionText":"report name","questionHelp":"some help 1","sortOrder":1,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"surveyor","questionHelp":"some help 2","sortOrder":2,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"asssigned to","questionHelp":"some help 3","sortOrder":3,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"client firstname","questionHelp":"some help 4","sortOrder":4,"isActive":true,"questionType":"NUMBER","options":""},{"questionText":"client lastname","questionHelp":"some help 5","sortOrder":5,"isActive":true,"questionType":"STARS","options":""},{"questionText":"report reference","questionHelp":"some help 6","sortOrder":6,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"date of inspection","questionHelp":"some help 7","sortOrder":7,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"house / building number","questionHelp":"some help 8","sortOrder":8,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"address line 1","questionHelp":"some help 9","sortOrder":9,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"address line 2","questionHelp":"some help 10","sortOrder":10,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"postcode","questionHelp":"some help 11","sortOrder":11,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"weather conditions","questionHelp":"some help 12","sortOrder":12,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"property status","questionHelp":"some help 13","sortOrder":13,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"property type","questionHelp":"property help","sortOrder":14,"isActive":true,"questionType":"LIST","options":"Bungalow;Semi-detatched, Detached, Terraced, Flat"}]},{"name":"Overall opinion","surveyQuestions": [{"questionText":"our overall opinion of the property","questionHelp":"some help 15","sortOrder":1,"isActive":true,"questionType":"TEXT","options":""}]},{"name":"About the property","surveyQuestions": [{"questionText":"type of property","questionHelp":"some help 17","sortOrder":1,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"approximate year property was built","questionHelp":"some help 18","sortOrder":2,"isActive":true,"questionType":"NUMBER","options":""},{"questionText":"approximate year the property was extended","questionHelp":"some help 19","sortOrder":3,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"approximate year the property was converted","questionHelp":"some help 20","sortOrder":4,"isActive":true,"questionType":"TEXT","options":""},{"questionText":"information relevant to flats and maisonettes","questionHelp":"some help 21","sortOrder":5,"isActive":true,"questionType":"TEXT","options":""}]}]}
And the pretty print version:
{
"sections": [
{
"name": "About the inspection",
"surveyQuestions": [
{
"questionText": "report name",
"questionHelp": "some help 1",
"sortOrder": 1,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "surveyor",
"questionHelp": "some help 2",
"sortOrder": 2,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "asssigned to",
"questionHelp": "some help 3",
"sortOrder": 3,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "client firstname",
"questionHelp": "some help 4",
"sortOrder": 4,
"isActive": true,
"questionType": "NUMBER",
"options": ""
},
{
"questionText": "client lastname",
"questionHelp": "some help 5",
"sortOrder": 5,
"isActive": true,
"questionType": "STARS",
"options": ""
},
{
"questionText": "report reference",
"questionHelp": "some help 6",
"sortOrder": 6,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "date of inspection",
"questionHelp": "some help 7",
"sortOrder": 7,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "house / building number",
"questionHelp": "some help 8",
"sortOrder": 8,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "address line 1",
"questionHelp": "some help 9",
"sortOrder": 9,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "address line 2",
"questionHelp": "some help 10",
"sortOrder": 10,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "postcode",
"questionHelp": "some help 11",
"sortOrder": 11,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "weather conditions",
"questionHelp": "some help 12",
"sortOrder": 12,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "property status",
"questionHelp": "some help 13",
"sortOrder": 13,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "property type",
"questionHelp": "property help",
"sortOrder": 14,
"isActive": true,
"questionType": "LIST",
"options": "Bungalow;Semi-detatched, Detached, Terraced, Flat"
}
]
},
{
"name": "Overall opinion",
"surveyQuestions": [
{
"questionText": "our overall opinion of the property",
"questionHelp": "some help 15",
"sortOrder": 1,
"isActive": true,
"questionType": "TEXT",
"options": ""
}
]
},
{
"name": "About the property",
"surveyQuestions": [
{
"questionText": "type of property",
"questionHelp": "some help 17",
"sortOrder": 1,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "approximate year property was built",
"questionHelp": "some help 18",
"sortOrder": 2,
"isActive": true,
"questionType": "NUMBER",
"options": ""
},
{
"questionText": "approximate year the property was extended",
"questionHelp": "some help 19",
"sortOrder": 3,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "approximate year the property was converted",
"questionHelp": "some help 20",
"sortOrder": 4,
"isActive": true,
"questionType": "TEXT",
"options": ""
},
{
"questionText": "information relevant to flats and maisonettes",
"questionHelp": "some help 21",
"sortOrder": 5,
"isActive": true,
"questionType": "TEXT",
"options": ""
}
]
}
]
}
Disclaimer: the code looks messy but it's late and it works!