Perspective JSON as parameter for script

Hello, I’m using a JSON from a perspective view to build a sort of wizard.

I made some input box binding to some properties of the JSON and everything is ok, then I have two buttons with some scripts and I’d like to understand what’s going on.

Pressing the first button I read the JSON and I pass it as an argument to a script function like this :

 obj = self.view.getChild("root").custom.porta #<-- json from perspective
 func1.Go(obj)
 func2.Go(obj)

func1 : modify state of JSON
func2 : print out JSON obj

I notice that func2 seams to work on a not updated JSON, and if I print the state I can clearly see that the attributes are not being modified from func1.

However, if I check the JSON state from the GUI I can see that the attributes are changed.

If i repeat the process, i can see on the output that the JSON is updated from the last call, so i end up always with one iteration of delay.

Button 1 :

 obj = self.view.getChild("root").custom.porta #<-- json from perspective
 func1.Go(obj)
 sleep(10)
 func2.Go(obj)

Button 2 :

 obj = self.view.getChild("root").custom.porta #<-- json from perspective
 system.perspective.print(obj)

Clicking the first button and then the second one, I can see JSON printed out is correctly being modified from func1, however after 10 seconds I got the printed text from func2 JSON printed is not updated.

I noticed some strange behavior when working with arrays too.

Am I missing something or am I not supposed to work in this way?



Adding a note :

A way to reproduce is to create a JSON like this one :
Schermata 2021-10-26 alle 18.07.15

First button Script :

obj = self.view.custom.test
	
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1

index get incremented by 1.

Second Button :

self.view.custom.test.val_1.index += 1
self.view.custom.test.val_1.index += 1
self.view.custom.test.val_1.index += 1

It work as expected.

Thank you

I’m guessing you’re updating the view param, not the obj you’re passing to your functions.
try

obj = self.view.getChild("root").custom.porta #<-- json from perspective
func1.Go(obj)
obj = self.view.getChild("root").custom.porta #<-- json from perspective 
func2.Go(obj)

and see if it works as intended.

Hi,
thank you but this was one of the first test i did, Is two days I’m trying to understand what’s going on,
i did a lots of test :slight_smile:

can you show func1 and 2?
objects and arrays work with references, so depending what you do with them, they might (not) update the reference.

I don't really have func1 and func2

objects and arrays work with references

I expected them as work like them, but you can see there is something going on on this step

obj = self.view.custom.test
	
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1
obj['val_1']['index'] +=1

and i think is the same thing that happen when i pass the object to different functions

I've had the same problem.I use this, to get individual objects.

import deepcopy from copy

.

Thank you, I will try this solution.

deepcopy doesnt really work for me it seems. giving some type errors “com.inductiveautomation.perspective.gateway.script.PropertyTreeScriptWrapper$ObjectWrapper()”

however this works:

	obj = self.view.custom.test
	index=obj['val_1']['index']
	index +=1
	index +=1
	index +=1
	index +=1
	index +=1
	obj['val_1']['index'] = index

Here is no error with me.

for text it works, but when there are objects in it

Also i would like to note that you are not using json. You are using objects which just look like json.
Json is just a structure^^

I tried list, tuple, and dictionary, maybe it doesn’t work for some object.

most of the things im trying doesnt work :stuck_out_tongue: maybe just have a thing for trying the impossible xd i always find the edge cases xd

Thank you for the information,
is that a json from perspective being casted in a python dict? or is not json even at the beginning?

There is definitly some json involved. The views get saved as json. But there first is a whole bunch of java in between.

I found a very ugly solution but it’s working so I’m going with this one for the moment.

I start the script by encoding/decoding the JSON(?) from perspective session, this way I know I’m working with a decoupled pyDictionary and passing this object to functions work as expected.

Then at the bottom of the script i assign the pyDictionary back to the perspective object.

porta = system.util.jsonEncode( self.view.getChild("root").custom.porta )
porta = system.util.jsonDecode( porta )

	
Models.Wizard.ComposeItemsCoordinateFromRules(porta)
Models.Wizard.CalcoloPuntiSaldaturaManiglia(porta)
Models.Wizard.ComposeOmega(porta)
Models.Wizard.CalcoloPuntiSaldaturaDeviatori(porta)
Models.Wizard.CalcoloPuntiSaldaturaCerniere(porta)
Models.Wizard.CalcoloPuntiSaldaturaOmega(porta)

self.view.getChild("root").custom.porta = porta
3 Likes

This code creates a deepcopy (the correct way):

If you put it in a project script it should be easyenough to use

	def sanitize_tree(element):
		    if hasattr(element, '__iter__'):
		        if hasattr(element, 'keys'):
		            return dict((k, sanitize_tree(element[k])) for k in element.keys())
		        else:
		            return list(sanitize_tree(x) for x in element)
		    return element
		    
	obj = sanitize_tree(self.view.custom.test)
			
	obj['val_1']['index'] +=1
	obj['val_1']['index'] +=1
	obj['val_1']['index'] +=1
	obj['val_1']['index'] +=1
	obj['val_1']['index'] +=1
	
	self.view.custom.test = obj