# Test variable type

**URL:** <https://forum.inductiveautomation.com/t/test-variable-type/67326>\
**Category:** Ignition\
**Tags:** ignition81, scripting, perspective\
**Created:** [December 7, 2022, 9:31am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326 "2022-12-07T09:31:56Z")\
**Posts on this page:** 12\
**Page:** 1

<div class="post-metadata">

**Author:** ![flavien](https://avatars.discourse-cdn.com/v4/letter/f/f475e1/32.png) [@flavien](https://forum.inductiveautomation.com/u/flavien)\
**Post date:** [December 7, 2022, 9:31am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/1 "2022-12-07T09:31:57Z")

</div>

Hello,

Is it possible to check if a variable is :

- dict or DotReferenceJythonMap
- list or JsonifiableArrayList  
?  
Thanks

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 7, 2022, 9:40am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/2 "2022-12-07T09:40:05Z")

</div>

A script can do it:

```python
isinstance(your_object, (dict, DotReferenceJythonMap))

```

You'll need to import the exotic types you want to test against.

edit:  
You might want to use parents of some classes, for example `AbstractJythonMap` instead of `DotReferenceJythonMap`. Your call.

---

<div class="post-metadata">

**Author:** ![flavien](https://avatars.discourse-cdn.com/v4/letter/f/f475e1/32.png) [@flavien](https://forum.inductiveautomation.com/u/flavien)\
**Post date:** [December 7, 2022, 11:06am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/3 "2022-12-07T11:06:53Z")

</div>

Thanks  
I've already tried isinstance() but I have a message : DotReferenceJythonMap is not defined.

How can I call DotReferenceJythonMap and AbstractJythonMap ?

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 7, 2022, 11:52am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/4 "2022-12-07T11:52:26Z")

</div>

As I said:

> [@pascal.fragnoud](#):
>
> You'll need to import the exotic types you want to test against.

`from com.inductiveautomation.ignition.common.script.abc import AbstractJythonMap`

You'll need to search the javadocs to find exactly what you need to import.

---

<div class="post-metadata">

**Author:** ![paul-griffith](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/paul-griffith/32/37249_2.png) [@paul-griffith](https://forum.inductiveautomation.com/u/paul-griffith)\
**Post date:** [December 7, 2022, 11:18pm UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/5 "2022-12-07T23:18:59Z")

</div>

Better question: why do you feel you need to do this? Duck typing is a better bet than relying on internal class specifics.

---

<div class="post-metadata">

**Author:** ![flavien](https://avatars.discourse-cdn.com/v4/letter/f/f475e1/32.png) [@flavien](https://forum.inductiveautomation.com/u/flavien)\
**Post date:** [December 15, 2022, 10:36am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/6 "2022-12-15T10:36:40Z")

</div>

@paul-griffith I don't understand "Duck typing". Do you have an example ?

I try to test PyLong variable too.

Do you mean that below ?

```auto
try:
	project_id = value*1
except:
	project_id = None
	
res = device.getList({'project_id':project_id})

```

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 15, 2022, 10:57am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/7 "2022-12-15T10:57:23Z")

</div>

> [@flavien](#):
>
> I don't understand "Duck typing"

if it quacks like a duck, walks like a duck, etc... then you can pass it to any function that accepts a duck.  
Or something.

You should try to answer this:

> [@paul-griffith](#):
>
> Better question: why do you feel you need to do this?

---

<div class="post-metadata">

**Author:** ![flavien](https://avatars.discourse-cdn.com/v4/letter/f/f475e1/32.png) [@flavien](https://forum.inductiveautomation.com/u/flavien)\
**Post date:** [December 15, 2022, 11:08am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/8 "2022-12-15T11:08:46Z")

</div>

🥱  
SO ...  
In my scripts or bindings, I test my variables to deal with unexpected errors. But in Ignition you have a lot of specific variables like JythonMap, PyLong, ...

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [December 15, 2022, 11:14am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/9 "2022-12-15T11:14:54Z")

</div>

That's where duck typing comes in.

Let's say your function takes an object and tries to call its `.foo()` method.  
Instead of checking that the object is the type you expected, you can check if it has a method called `foo`  
Basically, you're not asking "are you a duck ?", you're asking "can you quack ?"

---

<div class="post-metadata">

**Author:** ![tyler.bennett](https://avatars.discourse-cdn.com/v4/letter/t/f04885/32.png) [@tyler.bennett](https://forum.inductiveautomation.com/u/tyler.bennett)\
**Post date:** [April 17, 2024, 7:40am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/10 "2024-04-17T07:40:46Z")

</div>

Here is what I have been using to test if a variable is a dict like object or list like object ([lifted from here](https://forum.inductiveautomation.com/t/bug-system-util-sendmessage-fails-with-remoteservers-when-payload-is-not-a-dict/55040/7)):

> [@\[Bug\] system.util.sendMessage fails with remoteServers when payload is not a dict](https://forum.inductiveautomation.com/t/bug-system-util-sendmessage-fails-with-remoteservers-when-payload-is-not-a-dict/55040/7):
>
> ```auto
> def _isDictLikeObject(value):
> return 'iteritems' in dir(value)
> 
> def _isListLikeObject(value):
> return 'append' in dir(value)
> 
> ```

I'm curious if others have recommendation for better/preferred "Duck typing" methodology to detect a dict like objects or list like objects.

I ran into the issue with `DotReferenceJythonMap` types when I used a binding on a Perspective view custom property to create a list of dicts. I then tried to reference each dict in other property bindings with a script transform, attempting to merge with other programmatically created dicts. My custom method to merge dictionaries failed in some weird ways due to the `DotReferenceJythonMap` type.

Here is my previous custom merge function ([lifted from here](https://stackoverflow.com/questions/10703858/python-merge-multi-level-dictionaries)) that uses type checking.

```python
def merge(d1, d2):
	
	import collections 
	
	for k,v2 in d2.items():
		v1 = d1.get(k) # returns None if v1 has no value for this key
		if ( isinstance(v1, collections.Mapping) and 
			isinstance(v2, collections.Mapping) ):
			merge(v1, v2)
		else:
			d1[k] = v2
			
	return d1

```

Here is my revised custom merge function that uses "duck typing".

```python
def merge_test(d1, d2):
	for k,v2 in d2.items():
		v1 = d1.get(k)
		if ( 'iteritems' in dir(v1) and 'iteritems' in dir(v2) ):
			merge(v1, v2)
		else:
			d1[k] = v2
	return d1

```

Not sure if my examples are ideal (I welcome feedback) but the thread was light on actual examples so I thought I'd put these out there..

**One last note...** Notably the `system.util.jsonEncode()` function does not handle the object type `systemcom.inductiveautomation.perspective.gateway.script.DotReferenceJythonMap` type, nor does it handle many (any) of the other dict/list like wrapper objects Ignition like to create.

---

<div class="post-metadata">

**Author:** ![pascal.fragnoud](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pascal.fragnoud/32/24728_2.png) [@pascal.fragnoud](https://forum.inductiveautomation.com/u/pascal.fragnoud)\
**Post date:** [April 17, 2024, 8:00am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/11 "2024-04-17T08:00:36Z")

</div>

If I understand correctly, the issue stems from the fact that DotReferenceJythonMap doen't support assignments.  
What I do is create a new dict from the jython map AND the values I want to add to it

```python
dict(jython_map, **new_values)

```

Let's say I wanted to grab a list of objects from a perspective property, and add `'forty_two': 42` to each of those objects, it would look like this (assuming this is a script transform and `value` is the list referenced by a property binding):

```python
return [
	dict(
		row,
		**{'forty_two': 42}
	) for row in value
]

```

---

<div class="post-metadata">

**Author:** ![pturmel](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/pturmel/32/3295_2.png) [@pturmel](https://forum.inductiveautomation.com/u/pturmel)\
**Post date:** [April 17, 2024, 11:55am UTC](https://forum.inductiveautomation.com/t/test-variable-type/67326/12 "2024-04-17T11:55:12Z")

</div>

> [@tyler.bennett](#):
>
> I'm curious if others have recommendation for better/preferred "Duck typing" methodology to detect a dict like objects or list like objects.

Use python's builtin `hasattr()` function instead of using `dir()`. The latter is rather expensive in comparison.
