Iterating Through and Accessing Nested JSON Values
Hi,
I'm trying to figure out why I'm unable to iterate through a dynamic array and access the nested objects.
Using the NHS PDS FHIR API in the NHS sandbox environment, I'm querying the PDS endpoint using a sample NHS Number to retrieve a patient's demographics. My Business Operation reads the response data and passes it back to my Business Process where I intend on iterating through certain nested objects. The data present in these nested objects will decide what happens next in the process.
In the JSON snippet below, I'm attempting to access the values of code and display.
"meta": {
"versionId": "2",
"security": [
{
"system": "http://terminology.hl7.org/CodeSystem/v3-Confidentiality",
"code": "U",
"display": "unrestricted"
}
]
}
JSONJSON
I am able to get the security array but unsure how to get the value of the keys within that. I've attempted iterating through and using %Get().
PDSINTEGRATION>set securityArray=metaDynObj.security
PDSINTEGRATION>zw securityArray
securityArray=[{"system":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality","code":"U","display":"unrestricted"}] ; <DYNAMIC ARRAY>
PDSINTEGRATION>set iterator=securityArray.%GetIterator()
PDSINTEGRATION>while iterator.%GetNext(.key,.val) { write !, "Element index: "_key_", value: "_val }
Element index: 0, value: 117@%Library.DynamicObject
PDSINTEGRATION>zw securityArray.%Get("code")
{"system":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality","code":"U","display":"unrestricted"} ; <DYNAMIC OBJECT>
Shell SessionShell Session
Thanks
Maybe there are tools to dump a dynamic object, I don't know, but you can always write your own short method
/// obj: a dynamic object /// opt: an option, how to display array elements /// 0: just show the index number /// 1: show the parenthesized index /// 2: show index number in a %Get() method /// tag: optional, the name of the <obj> variable /// ClassMethod DumpJSON(obj, opt = 2, tag = "") { set itr=obj.%GetIterator(), arr=obj.%IsA("%DynamicArray") set:tag]"" tag=tag_"." while itr.%GetNext(.key, .val) { set:arr key=$case(opt, 2:"%Get("_key_")", 1:"("_key_")", :key) if $isobject(val), val.%IsA("%DynamicAbstractObject") { do ..DumpJSON(val,opt,tag_key) } else { write tag,key,": ",val,! } } }
For ease of use, put it into the %ZLANGC00.mac, for example
%ZLANGC00 ; Command extensions // Dump a dymanmic object ZDDUMP(obj,opt,tag) Public { do ##class(your.utility).DumpJSON(obj,.opt,.tag) }
For the data, you mentioned above, the following will be displayed
set metaDynObj={"versionId":"2","security":[{"system":"http://terminol....} zddump metaDynObj::"metaDynObj" metaDynObj.versionId: 2 metaDynObj.security.%Get(0).system: http://terminology.hl7.org/CodeSystem/v3-Confidentiality metaDynObj.security.%Get(0).code: U metaDynObj.security.%Get(0).display: unrestricted zddump [11,22,33] 0: 11 1: 22 2: 33 zddump [11,22,33]:1:"x" x.(0): 11 x.(1): 22 x.(2): 33
Thank you for posting that, good to know for future reference. I did find an alternative post by Eduard that lists the path for each value which looks to be working well.
https://community.intersystems.com/node/457371
Warning: what I describe here is not part of any released IRIS version. It is still in development and details might change.
We are working on an implementation of something we call "ASQ". This is intended to be a superset of the ISO Standard "JSON Path Language" (JPL). I suspect our current implementation will not meet all of your requirements but perhaps you will find this interesting:
USER>set obj = {"meta":{"versionId":"2","security":[{"system":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality","code":"U","display":"unrestricted"}]}} USER>zw obj.apply("$[*].meta.security[*].system") ["http://terminology.hl7.org/CodeSystem/v3-Confidentiality"] ; <DYNAMIC ARRAY>
We can repeat this same pattern but remove the security field value's enclosing array and we see the same result:
USER>set obj = {"meta":{"versionId":"2","security":{"system":"http://terminology.hl7.org/CodeSystem/v3-Confidentiality","code":"U","display":"unrestricted"}}} USER>zw obj.apply("$[*].meta.security[*].system") ["http://terminology.hl7.org/CodeSystem/v3-Confidentiality"] ; <DYNAMIC ARRAY>
Of course there is more, much more. I have more complex examples if you are interested.
-Dan
Check this example. It iterates all JSON elements, and also outputs the corresponding paths to access them.