Perform API GET and convert the resulting Json as tag values

I have a few API GETs that I am attempting to use for communication between our machines and an ERP. Using the Postman application I am able to send the GET request and receive a response (Only the names, locations and events have been changed while the structure is still intact):

resultJsonFromAPI.json (2.6 KB)

I plan on most of this information being useful to me in the future but for now this particular API has the "ItemNo" and "UOM" values that I need. I would like to store these values as a tag so I can use them elsewhere. I am able to perform HTTP bindings in Perspective on a TextField and then configure my transform to

{value}[0]["UOM"]

and it returns the expected value. I can also bind the http to a custom property and it will add all the objects in for me:

image

Unfortunately this does me no good apart from confirming that the API functions and it does seem to be a json.

I am struggling with trying to understand how to script this. I have seen several examples where people have mentioned dictionaries but I don't know what those are or how to make them, and I tried to modify this code but I have obviously butchered the formatting (this snippet is actually from a different API but the info is similar and the concept should be the same):

Header1="ProdOrderNo"
Header2="ProdOrderItemNo"
Header3="ItemNo"
Header4="ItemDesc"

##client = system.net.httpClient() wasnt working like i thought when i did client.get()
response = system.net.httpGet("http://apiroutehere")
data=[]
for key in response.json['ProdOrderComponentItemList']: #i thought this was the name of the primary header. pretty sure im wrong. 
	data.append([key['ProdOrderNo'],key['ProdOrderItemNo'],key['ItemNo'],key['ItemDesc']])
	
	headers=[Header1,Header2,Header3,Header4]
	listing=system.dataset.toDataSet(headers, data)
	system.tag.writeAsync(["[default]TagImWritingTo"], [len(data),listing])

I tried to make an expression tag and use jsonGet() but I again could not figure out the headers and I'm not even sure that I was performing the GET correctly. I will only be setting this up once and wont have to do it again (I'm not saying never though) so if I have to manually set up the tags then so be it.

I would greatly appreciate some guidance with where I should even be starting and what the appropriate approach even is. My scripting/Python knowledge is limited, heck I didn't even know what an API was 2 months ago, so thanks for your patience.
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
-----------------------------------------------------------------------------------------
Edit: So I have marked this as solved however I wanted to add some additional information since my API query parameter will change depending on which line I'm currently communicating from. I added two reference tags to obtain this value and keep all my stuff in one place.

image

I used a Value Changed script event on the relevant tag:

srcTag="pathToTagA"
tarTag="pathToTagB"
srcVal=system.tag.readBlocking(srcTag)[0].value
##allows the parameter for the GET to be dynamic with srcVal as a substitute
addressAPI="APIhttpaddress"+srcVal
response=system.net.httpGet(addressAPI)
system.tag.writeAsync(tarTag,response)

As a result I think the GET only occurs when the value changes (I made an assumption that should reduce the network traffic?) and "tarTag" is a document tag as suggested.
image
I set up a bunch of expression tags within my UDT that use jsonGet({[.]0jsonFGPalletList},"[0].ProdOrderNo") and substituted [0].ProdOrderNo with the required header. I was having a huge roadblock because I could not wrap my head around how to translate the information from the User Manual example that had clearly defined headers to my data that had none. I don't know how I finally made the connection but I did. I tested this and if the value that is passed as a API query param is not valid it will give Error_ExpressionEval as the result. I am satisfied with how it is setup but would also accept critique. Thanks for all the help.

Easiest I believe is to write the entire json string to a document tag (probably in a UDT), then have other expression tags in the UDT that use jsonGet to set their values without having to use any scripting.

2 Likes

Thanks! The document tag was the key. I did edit my main post with some extra info that clarified some of the struggles I had. Thank you for the help.

Instead of reinventing the wheel, consider using this free module from Kyvis Labs, it does all the API requests on the gateway side and is configured using a YAML file. It is a lot easier to configure as it makes a tag provider and makes the tags directly if configured to do so. Saves a lot of ad-hoc scripts and onChanges etc. Also it makes it easier for a more junior integrator to follow what is happening.

1 Like

Neat. I will look at this for the next time I need to perform API shenanigans. Thank you.