# Jsonata globalContext() inconsistent handling of string vs variable

**URL:** <https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845>\
**Category:** General\
**Created:** [23 April 2023 12:39 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845 "2023-04-23T12:39:14Z")\
**Posts on this page:** 8\
**Page:** 1

<div class="post-metadata">

**Author:** ![moebius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/moebius/32/2872_2.png) [@moebius](https://discourse.nodered.org/u/moebius)\
**Post date:** [23 April 2023 12:39 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/1 "2023-04-23T12:39:14Z")

</div>

When accessing a map object via jsonata globalContext, it does not work when the get method uses a variable - but using a string works.  
v 3.0.2

example:

```auto
[{"id":"8885e1d87c774eb3","type":"change","z":"f1e84ae7.4dcf98","name":"get with variable","rules":[{"t":"set","p":"payload","pt":"msg","to":"$globalContext(\"testmap\").get(payload)","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":877,"y":1033,"wires":[["e28f0de5eb5a8d25"]]},{"id":"f07e5a42e3af87ee","type":"inject","z":"f1e84ae7.4dcf98","name":"variable","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"MEQ0838051","payloadType":"str","x":615,"y":1082,"wires":[["8885e1d87c774eb3"]]},{"id":"e28f0de5eb5a8d25","type":"debug","z":"f1e84ae7.4dcf98","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"true","targetType":"full","statusVal":"","statusType":"auto","x":1138,"y":1012,"wires":[]},{"id":"1e367b4a4fcb63fb","type":"inject","z":"f1e84ae7.4dcf98","name":"config","props":[{"p":"payload"}],"repeat":"","crontab":"","once":false,"onceDelay":"2","topic":"","payload":"[{\"hm_addr\":\"MEQ0838051\",\"system\":\"hm\",\"type\":\"lock\"},{\"hm_addr\":\"MEQ0092869\",\"system\":\"hm\",\"type\":\"motion\"}]","payloadType":"json","x":615,"y":993.0000610351562,"wires":[["9ba31ab579766bd2"]]},{"id":"9ba31ab579766bd2","type":"function","z":"f1e84ae7.4dcf98","name":"load map","func":"var m = new Map()\n\nmsg.payload.forEach((item) => {\n m.set(item.hm_addr,item)\n});\n\nglobal.set(\"testmap\",m);\nreturn null\n","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":854.9993896484375,"y":964.982421875,"wires":[[]]},{"id":"5c49ee580fc41d67","type":"change","z":"f1e84ae7.4dcf98","name":"get with string","rules":[{"t":"set","p":"payload","pt":"msg","to":"$globalContext(\"testmap\").get(\"MEQ0838051\")","tot":"jsonata"}],"action":"","property":"","from":"","to":"","reg":false,"x":895,"y":1086,"wires":[["e28f0de5eb5a8d25"]]},{"id":"c9776cce0d6852d7","type":"inject","z":"f1e84ae7.4dcf98","name":"string","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"","payload":"MEQ0838051","payloadType":"str","x":633,"y":1135,"wires":[["5c49ee580fc41d67"]]}]

```

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 April 2023 13:05 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/2 "2023-04-23T13:05:12Z")

</div>

Clue might lie in the output of this function node?

```auto
const x = global.get("testmap");
node.warn(x instanceof Map)
node.warn(x instanceof Object)

const y = new Map()
node.warn(y instanceof Map)
node.warn(y instanceof Object)

```

Where you will find that it outputs FALSE, FALSE, TRUE, TRUE. Which is rather unexpected.

I think this is because the node get/set functions don't necessarily do what people expect. In that they may serialise/unserialise the data though even I'll admit that I was surprised that the got map was not an instance of Object. I've not yet worked out what it IS an instance of.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 April 2023 13:29 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/3 "2023-04-23T13:29:47Z")

</div>

OK, no, I'm wrong. That isn't the problem.

The problem is the opposite I believe. I've checked with both memory and file global variables and both do in fact return Map's.

Which means that it is JSONata that can't cope with a Map most likely. Maps are not standard JavaScript objects, they are, as you probably know, a special type of object and so some things we are used to doing with objects do not work.

For example `node.warn(Object.getPrototypeOf( new Map() ))` will fail with `TypeError: encodeObject Error: [Method Map.prototype.entries called on incompatible receiver #<Map>] Value: Object [Map]`. But it works fine with a standard object.

And `Object.prototype.toString.call(z)` will return `[object Map]` for a Map but `[object Object]` for a standard object.

Maps are weird. For example, you can do this with a Map: `map1.set({'a':1}, 97)` that is perfectly valid! If you do `console.log([...map1.keys()])`, you get something like this: `Array ["a", "b", "c", Object { a: 1 }]`. Very weird.

* * *

I still don't know why this returns FALSE though, it should return TRUE so something odd is happening.

```auto
const x = global.get("testmap");
node.warn(x instanceof Map)

```

And it is still true that you cannot directly serialise a Map with `JSON.stringify`. It will not work. So if you are using something like the the REDIS store for variables, I think `global.set` and get will fail.

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [23 April 2023 13:39 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/4 "2023-04-23T13:39:16Z")

</div>

When using the msg variable the map is not in base context so can not see the payload.  
use  
`$$.payload`  
So JSONata is looking in correct place.

This is an example why i always use $$ when referencing the msg context.

---

<div class="post-metadata">

**Author:** ![moebius](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/moebius/32/2872_2.png) [@moebius](https://discourse.nodered.org/u/moebius)\
**Post date:** [23 April 2023 13:41 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/5 "2023-04-23T13:41:14Z")

</div>

Thank you all for the quick investigation and help!

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [23 April 2023 13:43 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/6 "2023-04-23T13:43:44Z")

</div>

> [@E1cid](#):
>
> This is an example why i always use $$ when referencing the msg context.

Ah! I perhaps overlooked something in my response 😁

I'm glad it works. However I foresee maps creating more problems in the future for Node-RED. I've already fallen foul of them in my own code. Before now, we've mostly assumed we can serialise most things without too many issues and that is less true now.

---

<div class="post-metadata">

**Author:** ![E1cid](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/e1cid/32/77971_2.png) [@E1cid](https://discourse.nodered.org/u/E1cid)\
**Post date:** [23 April 2023 13:54 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/7 "2023-04-23T13:54:12Z")

</div>

Wondering if the map() is even needed here, would not a simple object do, the use `$lookup(object, payload)`

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [7 May 2023 13:54 UTC](https://discourse.nodered.org/t/jsonata-globalcontext-inconsistent-handling-of-string-vs-variable/77845/8 "2023-05-07T13:54:27Z")

</div>

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.
