How to get, ("fields") to Work in VBA-JSON - json

Summary
I am trying to access the deep levels of nested JSON that comes back from the API that I am working with at the moment. Using VBA-JSON through this process has been pretty easy, but I've ran into a little road block. For the most part, I've got this library to work properly, but I get an error anytime I try to grab an item that is nested in the JSON response (further than 2 JSON levels). I am going to submit this post, and then I'll go and gather some of the error codes that I am getting. Off the top of my head, I know that I get a Run-time error '13' when I try to use the code below that doesn't work. I think (could be wrong) that I am smart enough to understand the type mismatch error, but I don't know how to fix it.
This Works
For i = 1 To 20
ActiveSheet.Cells(i + 1, 5) = Json("issues")(i)("key")
ActiveSheet.Cells(i + 1, 6) = Json("issues")(i)("id")
Next
Doesn't Work
For i = 1 To 20
ActiveSheet.Cells(i + 1, 7) = Json("fields")(i)("summary")
Next
None of These Worked Either
ActiveSheet.Cells(i + 1, 7) = Json("fields")(i)("summary")
ActiveSheet.Cells(i + 1, 7) = Json("fields")("summary")
ActiveSheet.Cells(i + 1, 7) = Json("issues")("fields")("summary")
ActiveSheet.Cells(i + 1, 7) = Json("fields")("assignee")(i)("name")
ActiveSheet.Cells(i + 1, 7) = Json("issues")("fields")("assignee")(i)("name")
Updated with Some JSON
I edited the JSON that comes back for privacy reasons (obviously).
{
"expand": "schema,names",
"startAt": 0,
"maxResults": 50,
"total": 28,
"issues": [ {
"expand": "",
"id": "94581",
"self": "",
"key": "",
"fields": {
, "assignee": {}
, "status": {}
, "votes": {}
, "summary": ""
,
, "issuetype": {}
, "timespent": null,
}
}
,
{}
,
{}
,
{}
]
}
According to this data structure, my code should be looking at the right place, right?
Thoughts? :)
PS: Sorry if jargon is off, I'm a developer by hobby, not by job. :)

The Problem
Nested arrays were actually the problem. The 2'nd level of JSON items were not arrays, while, "fields" was.
To solve the problem, we need to add a (i + 1) to the code.
Working Code Example
''''''''
' Loop '
''''''''
For i = 1 To 20
ActiveSheet.Cells(i + 1, 5) = Json("issues")(i)("key")
ActiveSheet.Cells(i + 1, 6) = Json("issues")(i)("id")
ActiveSheet.Cells(i + 1, 7) = Json("issues")(i + 1)("fields")("summary")
ActiveSheet.Cells(i + 1, 8) = Json("issues")(i + 1)("fields")("watches")("watchCount")
ActiveSheet.Cells(i + 1, 9) = Json("issues")(i + 1)("fields")("workratio")
Next
Update :(
So, I got all of my code setup to run my report, and it was working, and then it randomly stops (I watched it do this on line 16 or so) and gives me another type mismatch error.
How were the rows 1-15 working, and then suddenly there is a type mismatch error?
lol...
Debugging now...
Update 2 :)
Simple mix up with the code structure, there wasn't a problem and the solution that I posted below works correctly.

Related

How to read JSON file in Prolog

I found a few SO posts on related issues which were unhelpful. I finally figured it out and here's how to read the contents of a .json file. Say the path is /home/xxx/dnns/test/params.json, I want to turn the dictionary in the .json into a Prolog dictionary:
{
"type": "lenet_1d",
"input_channel": 1,
"output_size": 130,
"batch_norm": 1,
"use_pooling": 1,
"pooling_method": "max",
"conv1_kernel_size": 17,
"conv1_num_kernels": 45,
"conv1_stride": 1,
"conv1_dropout": 0.0,
"pool1_kernel_size": 2,
"pool1_stride": 2,
"conv2_kernel_size": 12,
"conv2_num_kernels": 35,
"conv2_stride": 1,
"conv2_dropout": 0.514948804688646,
"pool2_kernel_size": 2,
"pool2_stride": 2,
"fcs_hidden_size": 109,
"fcs_num_hidden_layers": 2,
"fcs_dropout": 0.8559119274655482,
"cost_function": "SmoothL1",
"optimizer": "Adam",
"learning_rate": 0.0001802763794651928,
"momentum": null,
"data_is_target": 0,
"data_train": "/home/xxx/data/20180402_L74_70mm/train_2.h5",
"data_val": "/home/xxx/data/20180402_L74_70mm/val_2.h5",
"batch_size": 32,
"data_noise_gaussian": 1,
"weight_decay": 0,
"patience": 20,
"cuda": 1,
"save_initial": 0,
"k": 4,
"save_dir": "DNNs/20181203090415_11_created/k_4"
}
To read a JSON file with SWI-Prolog, query
?- use_module(library(http/json)). % to enable json_read_dict/2
?- FPath = '/home/xxx/dnns/test/params.json', open(FPath, read, Stream), json_read_dict(Stream, Dicty).
You'll get
FPath = 'DNNs/test/k_4/model_params.json',
Stream = <stream>(0x7fa664401750),
Dicty = _12796{batch_norm:1, batch_size:32, conv1_dropout:0.
0, conv1_kernel_size:17, conv1_num_kernels:45, conv1_stride:
1, conv2_dropout:0.514948804688646, conv2_kernel_size:12, co
nv2_num_kernels:35, conv2_stride:1, cost_function:"SmoothL1"
, cuda:1, data_is_target:0, data_noise_gaussian:1, data_trai
n:"/home/xxx/Downloads/20180402_L74_70mm/train_2.h5", data
_val:"/home/xxx/Downloads/20180402_L74_70mm/val_2.h5", fcs
_dropout:0.8559119274655482, fcs_hidden_size:109, fcs_num_hi
dden_layers:2, input_channel:1, k:4, learning_rate:0.0001802
763794651928, momentum:null, optimizer:"Adam", output_size:1
30, patience:20, pool1_kernel_size:2, pool1_stride:2, pool2_
kernel_size:2, pool2_stride:2, pooling_method:"max", save_di
r:"DNNs/20181203090415_11_created/k_4", save_initial:0, type
:"lenet_1d", use_pooling:1, weight_decay:0}.
where Dicty is the desired dictionary.
If you want to define this as a predicate, you could do:
:- use_module(library(http/json)).
get_dict_from_json_file(FPath, Dicty) :-
open(FPath, read, Stream), json_read_dict(Stream, Dicty), close(Stream).
Even DEC10 Prolog released 40 years ago could handle JSON just as a normal term . There should be no need for a specialized library or parser for JSON because Prolog can just parse it directly .
?- X={"a":3,"b":"hello","c":undefined,"d":null} .
X = {"a":3, "b":"hello", "c":undefined, "d":null}.
?-

VBA Parse Nested JSON

VBA Noob here. Please excuse any gaps in terminology etc.
I am trying to parse a JSON file into a spreadsheet using VBA-JSON v2.2.3 (c) Tim Hall - https://github.com/VBA-tools/VBA-JSON.
The JSON file looks like this:
{
"site": "{5BEC7C29-FF95-4ECC-9314-064B52618EEE}",
"from": "2017-01-16",
"to": "2017-01-22",
"timeSheet": [
{
"date": "2017-01-16",
"person": "{E2A5FDE1-33F8-43CA-A01D-5DD4A3A5E23A}",
"personName": "James Smith",
"company": "{B03CF7B3-0BE9-44B4-8E55-47782FDD87C0}",
"companyName": "Acme Company Ltd",
"minutes": "510",
"activities": [
{
"name": "Training",
"code": "TR",
"minutes": "240"
},
{
"name": "Administration",
"code": "AD",
"minutes": "150"
},
{
"name": "Payroll",
"code": "PR",
"minutes": "60"
},
{
"name": "Meal break",
"code": "",
"minutes": "60"
}
]
}
]
}
There may be any number of 'timeSheet' records, as well as any number of 'Activities' within each timeSheet including zero.
I want a row in the spreadsheet for each activity, with the name and other data outputted next to that days activities. Essentially showing a log of all the activities done, for how long and by who. To complicate issues, I still need the name etc outputting even if no activities are recorded. I will then fill with 'unallocated time' or something similar.
Below is as far as I have got (abridged), with an updated count of the activities occurring every loop. This feels a little hacky and doesn't give me what I am looking for, often adding additional rows and sometimes missing activities entirely.
i = 2
j = 1
activCount = CStr(JSON("timeSheet")(1)("activities").Count)
If activCount = 0 Then activCount = 1
ws.Cells(i, 1) = JSON("site")
ws.Cells(i, 2) = JSON("from")
ws.Cells(i, 3) = JSON("to")
For Each item In JSON("timeSheet")
For j = 1 To activCount
On Error Resume Next
ws.Cells(i, 4) = item("date")
ws.Cells(i, 5) = item("personName")
ws.Cells(i, 6) = item("companyName")
ws.Cells(i, 7) = item("minutes")
ws.Cells(i, 9) = item("activities")(j)("name")
ws.Cells(i, 10) = item("activities")(j)("code")
ws.Cells(i, 11) = item("activities")(j)("minutes")
activCount = CStr(JSON("timeSheet")(i)("activities").Count)
If activCount = 0 Then activCount = 1
i = i + 1
Next
Next
Can someone help? I have run out of ideas and have been working it for some time! Thank you. :)
This worked fine for me:
Sub TestJson2()
Dim ts, act
Dim Json As Object, c As Range
'reading json from a worksheet cell...
Set Json = JsonConverter.ParseJson(Range("A3").Value)
Set c = ActiveSheet.Range("C5")
'loop over timesheets
For Each ts In Json("timeSheet")
'loop over timesheet activities
For Each act In ts("activities")
c.Resize(1, 11).Value = Array(Json("site"), Json("from"), Json("to"), _
ts("date"), ts("personName"), ts("companyName"), _
ts("minutes"), act("name"), act("code"), _
act("minutes"))
Set c = c.Offset(1, 0)
Next act
Next ts
End Sub

AWS X-Ray Python SDK get_service_graph

I am trying to get JSON using get_service_graph() provided by AWS X-Ray Python SDK in AWS Lambda function. reference link
import boto3
from datetime import datetime
def lambda_handler(event, context):
client = boto3.client('xray')
response1 = client.get_service_graph(
StartTime=datetime(2017, 5, 20, 12, 0),
EndTime=datetime(2017, 5, 20, 18, 0)
)
return response1
However, when I passed StartTime and EndTime parameters, stack trace reports datetime type is not JSON serializable. I even tried the following way.
response1 = client.get_service_graph(
StartTime="2017-05-20 00:00:00",
EndTime="2017-05-20 02:00:00"
)
What's weird is, if EndTime is set as "2017-05-20 01:00:00", there is no error generated. Other than that, the same error occurred.
{
"stackTrace": [
[
"/usr/lib64/python2.7/json/__init__.py",
251,
"dumps",
"sort_keys=sort_keys, **kw).encode(obj)"
],
[
"/usr/lib64/python2.7/json/encoder.py",
207,
"encode",
"chunks = self.iterencode(o, _one_shot=True)"
],
[
"/usr/lib64/python2.7/json/encoder.py",
270,
"iterencode",
"return _iterencode(o, 0)"
],
[
"/var/runtime/awslambda/bootstrap.py",
104,
"decimal_serializer",
"raise TypeError(repr(o) + \" is not JSON serializable\")"
]
],
"errorType": "TypeError",
"errorMessage": "datetime.datetime(2017, 5, 20, 1, 53, 13, tzinfo=tzlocal()) is not JSON serializable"
}
I did try only use date, like datetime(2017, 5, 20). However, if I use two consecutive days as StartTime and EndTime, the runtime complains the interval can't be more than 6 hours. If I use same date, it only returns empty JSON. I don't know how to get granularity of get_service_graph().
I think Python SDK for AWS X-Ray might be premature, but I'd still like to seek help from someone who had the same experience. Thanks!
the right way is using datetime(2017, 5, 20) not a string... but can you try using only date... without time? at least the AWS docs shows an example exactly like yours but only yyyy-mm-dd without time

Plotting a function as a function of another function in Mathematica

I wasn't entirely sure what to search for, so if this question has been asked before, I apologize in advance:
I have two functions
R := Rref*mx(mx^(4/3) - C0)^(-1)
M := Mref*(mx + C1*mx^(-1)*((1 - C0*mx^(-4/3))^(-3) - 1))
where Rref, Mref, C0 and C1 are constants and mx is the variable. I need to plot R as a function of M. Surely there must be something available in Mathematica to do such a plot - I just can't seem to find it.
The comment is correct, in that what you have is a set of two "parametric equations". You would use the ParametricPlot command. However, the syntax of functions with parameters is sometimes tricky, so let me give you my best recommendation:
R[Rref_, C0_, C1_][mx_] = Rref*mx (mx^(4/3) - C0)^(-1);
M[Mref_, C0_, C1_][mx_] = Mref*(mx + C1*mx^(-1)*((1 - C0*mx^(-4/3))^(-3) - 1));
I like that notation better because you can do things like derivatives:
R[Rref,C0,C1]'[mx]
(* Output: -((4 mx^(4/3) Rref)/(3 (-C0 + mx^(4/3))^2)) + Rref/(-C0 + mx^(4/3)) *)
Then you just plot the functions parametrically:
ParametricPlot[
{R[0.6, 0.3, 0.25][mx], M[0.2, 0.3, 0.25][mx]},
{mx, -10, 10},
PlotRange -> {{-10, 10}, {-10, 10}}
]
You can box this up in a Manipulate command to play with the parameters:
Manipulate[
ParametricPlot[
{R[Rref, C0, C1][mx], M[Mref, C0, C1][mx]},
{mx, -mmax, mmax},
PlotRange -> {{-10, 10}, {-10, 10}}
],
{Rref, 0, 1},
{Mref, 0, 1},
{C0, 0, 1},
{C1, 0, 1},
{mmax, 1, 10}
]
That should do it, I think.

Catch exception in Mathematica without having to run computations twice

I have to run a number of NMinimize commands on various instances. Some of these runs failed to converge.
I want to identify which ones failed to converge and obtain the current solution that Mathematica found.
Searches on other posts suggested using Check[], but it does not return the result once it comes out of the error.
So currently, I have the inefficient implementation as follows:
allfit1 = ConstantArray[0,16];
For[i = 1, i <= 16, i++, (
allfit1[[i]] = Check[
{0, NMinimize[f[x,data[[i]]], x]},
{1, NMinimize[f[x,data[[i]]], x]}
]
)]
As you see I am having to execute NMinimize twice, which is wasteful and time consuming.
Is there a better way?
As a minor change: you could store the result in a variable:
Block[{res},
Check[{0, res = NMinimize[...]}, {1, res}]
]
You could do
Table[Reap#Quiet#Check[Sow#NMinimize[f[x, d], x]; 1, 0]~
Extract~{{1}, {2, 1, 1}}, {d, data}]