How do you embed variable in a variable in Jinja2? - jinja2

I pass in a value to my jinja2 template called "key". "Key" is a string like "user_id" or "birthdate". "key" is also a dictionary key. You would access it like {{key}} in jinja2. However, I want to access the value of "key" in a dictionary. "item" is an array of dictionaries. I want to do something like {{item.{{key}}}}, but this isn't proper syntax. How should I do this?

Assuming item is a list, you should access the offset in the list that you want (e.g. if you want offset of x, use item[x]) which would then be a dictionary. At that point you can use the dictionary .get() syntax:
item[x].get(key)

Related

Get "Value" from simple JSON using "Key" as variable Azure Logic Apps

I have defined a simple JSON
{
"12345": "Numbers",
"AAAAA": "AllAs",
"ABCXYZ": "AtoZ"
}
All I want to extract the value of "Key" when passed as a variable. I have tried body('Parse_JSON')['name'] but its failing.
I just want to get the value of what ever Key I am looking for as variable.
For those also just starting with logic apps - if its not immediately apparent;
At "Initialize Variable 2" you need to use the "Expression" tab to input the line
body('parse_JSON')?[variables('name')]
As per your comment as you are initializing ABCXYZ value and that you have already declared in inputs you can just type ABCXYZ in value rather than calling Name variable
Figured it !
body('parse_JSON')?[variables('name')]
The above does the following:
1- body('parse_JSON') gets the body of Parsed JSON
2- ?[variables('name')]gets the value of name which is equal to ABCXYZ
3- Returns AtoZ
I just want to add something here as I was looking for a way to use a dynamics value passed in to then use that to look up in a json body to translate that value to a different.
Mapping value eg. {"male":"M", "female":"F", "Non-Specific":"O"}
So I receive the value "Male" but I need that to return as M
to achieve this in a logic app the above partially gets you there.
body('Parse_JSON_gender_mapping')?[string(variables('received_gender'))]
I had to wrap my use of the variable for the value we received in string() function, even though the value was a string.

Azure | ADF | How to use a String variable to lookup a Key in an Object type Parameter and retrieve its Value

I am using Azure Data Factory. I'm trying to use a String variable to lookup a Key in a JSON array and retrieve its Value. I can't seem to figure out how to do this in ADF.
Details:
I have defined a Pipeline Parameter named "obj", type "Object" and content:
{"values":{"key1":"value1","key2":"value2"}}
Parameter definition
I need to use this pipeline to find a value named "key1" and return it as "value1"; "key2" and return it as "value2"... and so on. I'm planning to use my "obj" as a dictionary, to accomplish this.
Technically speaking, If i want to find the value for key2, I can use the code below, and it will be returned "value2":
#pipeline().parameters.obj.values.key2
What i can't figure out is how to do it using a variable (instead of hardcoded "key2").
To clear things out: I have a for-loop and, inside it, i have just a copy activity: for-each contents
The purpose of the copy activity is to copy the file named item().name, but save it in ADLS as whatever item().name translates to, according to "obj"
This is how the for-loop could be built, using Python: python-for-loop
In ADF, I tried a lot of things (using concat, replace...), but none worked. The simpliest woult be this:
#pipeline().parameters.obj.values.item().name
but it throws the following error:
{"code":"BadRequest","message":"ErrorCode=InvalidTemplate, ErrorMessage=Unable to parse expression 'pipeline().parameters.obj.values.item().name'","target":"pipeline/name_of_the_pipeline/runid/run_id","details":null,"error":null}
So, can you please give any ideas how to define my expression?
I feel this must be really obvious, but I'm not getting there.....
Thanks.
Hello fellow Pythonista!
The solution in ADF is actually to reference just as you would in Python by enclosing the 'variable' in square brackets.
I created a pipeline with a parameter obj like yours
and, as a demo, the pipeline has a single Set Variable activity that got the value for key2 into a variable.
This is documented but you need X-ray vision to spot it here.
Based on your comments, this is the output of a Filter activity. The Filter activity's output is an object that contains an array named value, so you need to iterate over the "output.value":
Inside the ForEach you reference the name of the item using "item().name":
EDIT BASED ON MORE INFORMATION:
The task is to now take the #item().name value and use it as a dynamic property name against a JSON array. This is a bit of a challenge given the limited nature of the Pipeline Expression Language (PEL). Array elements in PEL can only be referenced by their index value, so to do this kind of complex lookup you will need to loop over the array and do some string parsing. Since you are already inside a FOR loop, and nested FOR loops are not supported, you will need to execute another pipeline to handle this process AND the Copy activity. Warning: this gets ugly, but works.
Child Pipeline
Define a pipeline with two parameters, one for the values array and one for the item().name:
When you execute the child pipeline, pass #pipeline.parameters.obj.values as "valuesArray" and #item().name as "keyValue".
You will need several string parsing operations, so create some string variables in the Pipeline:
In the Child Pipeline, add a ForEach activity. Check the Sequential box and set the Items to the valuesArray parameter:
Inside the ForEach, start by cleaning up the current item and storing it as a variable to make it a little easier to consume.
Parse the object key out of the variable [this is where it starts to get a little ugly]:
Add an IF condition to test the value of the current key to the keyValue parameter:
Add an activity to the TRUE condition that parses the value into a variable [gets really ugly here]:
Meanwhile, back at the Pipeline
At this point, after the ForEach, you will have a variable (IterationValue) that contains the correct value from your original array:
Now that you have this value, you can use that variable as a DataSet parameter in the Copy activity.

Accessing a decoded json string value in twig

I am working on a Symfony project and need to loop through data to populate saved fields in a form (specifically the number of bed types in a property). I save the data in the database table as a json string, as follows:
{"2":"5","3":"0","4":"0","5":"0","6":"0","7":"0"}
This JSON follows the structure "BEDID": NUMBER OF BEDS. I implemented the solution regarding decoding json in twig as stated here https://stackoverflow.com/a/14504988/5194337 but I am having trouble actually being able to access each specific value in the decoded json. I use this in the twig template to decode the json (based on the fact my data is stored in a variable called specifics and website.id references one of multiple websites owned by the user:
{% set beds = specifics[website.id].0.standardBedTypes|json_decode %}
So, once I do this, I try and access the value of each number of beds as follows:
{{ beds[standard_bed.id] }}
standard_bed being the value in the for loop. But, when I load the page I get the following error:
Impossible to access a key "2" on an object of class "stdClass" that
does not implement ArrayAccess interface.
I guess this means that the decoded value of the json is technically not an array, but I cannot think of any other method of referencing each value, so help with this is appreciated.
From the documentation here, you can pass it as an option. See the options here.
You want to pass JSON_OBJECT_AS_ARRAY
Decodes JSON objects as PHP array.
So basically you want to do:
{% set beds = specifics[website.id].0.standardBedTypes|json_decode(constant('JSON_OBJECT_AS_ARRAY')) %}
If you want to access to objects properties, you can do it using the attribute function.

Is {0:{"id":1,...},{"id:2,....}} a other reprensation of a JSON list like [{"id":1,...},{"id:2,....}]

I have a little dilema. I have a backend/Frontend Application that comunicates with a JSON based REST Api.
The backend is written in PHP(Symfony/jmsserializer) and the Frontend in Dart
The communication between these two has a little Problem.
For most List Data the backend responds with a JSON like
[{"id":1,...},{"id:2,....}]
But for some it responds with
{"0":{"id":1,...}, "1":{"id:2,....}}
Now my Question is should the backend respond with the later at all or only with the first?
Problem
You usually have a list of objects. You sometimes get an object with sub-objects as properties.
Underlying issue
JS/JSON-Lists are ordered from 0 upwards which means that if you have PHP-Array which does not respect this rule json_encode will output a JS/JSON-Object instead using the numeric indices as keys.
PHP-Arrays are ordered maps which have more features that the JSON-Lists. Whenever you're using those extra features you won't be able to translate directly into JSON-Lists without loosing some information (ordering, keys, skipped indices, etc.).
PHP-Arrays and JSON-Objects on the other hand are more ore less equivalent in terms of features and can be correctly translated between each other without any loss of information.
Occurence
This happens if you have an initial PHP-Array of values which respects the JS/JSON-List rules but the keys in the list of objects are modified somehow. For example if you have a custom indexing order {"3":{}, "0":{}, "1":{}, "2":{}} or if you have (any) keys that are strings (ie. not numeric).
This always happens if you want to use the numeric id of the object as the numeric index of the list {"123":{"id": 123, "name": "obj"}} even if the numeric ids are in ascending order... so long as they are not starting from 0 upwards it's not a json-list it's a json-object.
Specific case
So my guess is that the PHP code in the backend is doing something like fetching a list of objects but its modifying something about it like inserting them by (string) keys into the array, inserting them in a specific order, removing some of them.
Resolution
The backend can easily fix this by using array_values($listOfObjects) before using json_encode which will reindex the entire list by numeric indices of ascending value.
Arrays and dictionaries are two separate types in JSON ("array" and "object" respectively), but PHP combines this functionality in a single array type.
PHP's json_encode deals with this as follows: an array that only contains numeric keys ($array = ['cat', 'dog']) is serialized as JSON array, an associative array that contains non-numeric keys ($array = ['cat' => 'meow', 'dog' => 'woof']) is serialized as JSON object, including the array's keys in the output.
If you end up with an associative array in PHP, but want to serialize it as a plain array in JSON, just use this to convert it to a numerical array before JSON encoding it: $array = array_values($array);

Neo4j node property containing raw json as metadata

Is this possible to have a node property as json raw string and to filter on it with cypher ?
I have a node with some defined properties and metadata (json raw string).
I would like to select or filter on those metadata property.
This is something like this :
START movie=node:TYPE_INDEX(Type = 'MOVIE') // Start with the reference
MATCH movie-[t:TAG]->tag
WHERE collect(movie.Metadata).RatingPress > 3
RETURN distinct movie.Label
And metadata are something like this :
{"RatingPress" : "0","RatingSpectator" : 3"}
I have expected to use collect function in order to call the property like this :
collect(movie.Metadata).RatingPress
But, of course it fails...
Is this a way to bind some json string from a node property with cypher ?
Thanks for your help
That's going against the principles of properties. Why not set the properties in the JSON metadata directly on the node?
But to answer your question:
No, cypher has no knowledge about JSON.
We treat the entire Node as a JSON blob. Since Neo4j doesn't support hierarchical properties, we flatten out the JSON into delimited property names on save and unflatten them on read. You can then form Cypher queries on (for example) property name "foo.bar.baz". The queries tend to look a bit funky because you'll need to quote them using single back quotes, but it works.