Expressions for referencing previous results

I have to admit that even after years of use I still find the referencing of data from previous node not very straight forward.

I have this input data:

Now what I am trying to create through the expression:

{
  "expires": 3600,
  "dashboard": { "annotations": { ... }},
}

The first approach was:

{
  "expires": 3600,
  "dashboard": {{ $json.dashboard }},
}

But that shows in the preview as:

{
  "expires": 3600,
  "dashboard": [Object: {"annotations": {}}],
}

Why the Object?

The input says “Item 1” - so this should be an array of item 1.
But that would suggest more something like $json[0].dashboard.
But neither that nor $json.dashboard[0] give the result I am looking for.

This all feels a little hard.
I must be missing something.

What’s the way to go here?

This is with n8n version 0.217.2

Hey @tcurdt,

When you run it do you still see the same thing? Is there also any data in the annotations or is it empty? If you can share the JSON I can take a quick look and pop something together for you.

When you run it do you still see the same thing?

It will become invalid json when I run it.
So yes, seems to be consistent.

Is there also any data in the annotations or is it empty?

Here is a slightly redacted (but more detailed) version of the input

[{
	"meta": {
		"type": "db",
		"canSave": false,
		"canEdit": false,
		"canAdmin": false,
		"canStar": true,
		"canDelete": false
	},
	"dashboard": {
		"annotations": {
			"list": [{
				"builtIn": 1,
				"datasource": {
					"type": "datasource",
					"uid": "grafana"
				}
			}]
		},
		"editable": true,
		"id": 20,
		"from": "now-30d",
		"to": "now"
	},
	"timepicker": {},
	"timezone": "",
	"title": "Backend",
	"version": 42
}]

If you can share the JSON I can take a quick look and pop something together for you.

Much appreciated!

That said, the main focus for me is to understand how this meant to be done.
The API and UI part just isn’t particular clear to me.

If you can come up with something that might be a good basis for talking about the concepts.

Hey @tcurdt,

Sorry for the delay, So looking at that data I would typically do what you tried in your first approach but if I was sending it in say an HTTP Request node I would do {{ JSON.stringify( $json.dashboard ) }}.

Typically you would only need to do [x] if the item is in an array but because it isn’t we can just call it directly. As an example the workflow below sets you data in the Code node and the HTTP request node posts the the data to webhook.site.

In webhook.site this looks like…

But this just adds to the confusion of the API.

{   "expires": 3600,   "dashboard": {{ JSON.stringify($json.dashboard) }} }

That would turn the $json.dashboard into a string.
And I would expect this to be:

{ "expires": 3600, "dashboard": "{ \"annotations\": { ... } " }

not

{ "expires": 3600, "dashboard": {"annotations":{ .... } }

And I still don’t understand why

{
  "expires": 3600,
  "dashboard": {{ $json.dashboard }},
}

results in

{
  "expires": 3600,
  "dashboard": [Object: {"annotations": {}}],
}

Not to mention the 1 vs n items question.

If you had some explanations - that would be great.

Thanks for the help, @Jon

Hey @tcurdt,

Oddly enough when I did just the $json.dashboard I got the output as expected but it was an object and the input I was using expected a string.

If you try the same thing with the output from the code node so you still get the missing value? I also found that it would output [object object] which was I did the stringify.

A lot of the time just using the expression is right but if you are using an object in a string you can run into some issues which isn’t unique to n8n

This part of n8n still feels very “rough”, if not to say broken.
I am still utterly confused about the behaviour.
I can make things work - but it feels awkward.

What I ended up doing was adding another Code node in front.

const b = $input.first().json
return {
  "name": "Test",
  "expires": 3600,
  "dashboard": b.dashboard,
}

And then on the HTTP node I can use {{ JSON.stringify($json) }} for the body.

That’s the cleanest solution I found so far.

Hey @tcurdt,

I guess it comes down to the input field and where it is going. So is it a string expected or json and is the input field a string or a json field.

After a few workflows you will get the hang of it and are working on improvements to how data is transformed.

You shouldn’t need a code node for it though as I showed in the example but one of the neat things with n8n is there is many ways you can do the same thing.

The way I understand it it’s just an array of objects [{},{},{}] (3 items in this example) that is getting passed through a pipeline of nodes. Which is why a JSON.stringify feels completely out of place.

And it is awkward from a type perspective.

{   "expires": 3600,   "dashboard": {{ JSON.stringify($json.dashboard) }} }

The return type of JSON.stringify($json.dashboard) is a string.

$ node
Welcome to Node.js v18.14.2.
Type ".help" for more information.
> { dashboard: JSON.stringify({}) }
{ dashboard: '{}' }

…and not { dashboard: {} }

While it can be explained why it works in this case, it feels very awkward and fragile.
The approach with the additional Code node that transforms the data and then have the expression just stringify feels more verbose - but also cleaner. I guess I rather stick with that for now.

It’s not my first rodeo. Just the time with the new version of Code node.
But the the API/interface of the Code node has always been awkward.

Anyway. It works now.

Thanks for trying to help.

1 Like

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