I'm looking to parse a JSON object dynamically in a Liquid.
So far my efforts have been in vain as you can't loop over an object with a regular for loop.
The amount of properties in the ticket_attributes objects is dynamic and can vary in keynames.
Input object:
{
"action": "insert",
"state": "New",
"ticket_attributes": {
"category": "Event",
"user_name": "Customer ",
"prop3":"data1",
"prop4":"data1",
},
"ticket_number": "INC9190433"
}
Liquid snippets used that don't work:
{% for prop in content.ticket_attributes %}
{{prop[0]}}:{{prop[1]}}
{% endfor %}
{% for item in content.ticket_attributes %}
{{ forloop.index }}: {{ item.name }}
{% endfor %}
Any pointers on how to solve this inside the template?
According to some test, it seems liquid in azure logic app doesn't support loop hash. I think we can implement this requirement outside azure logic app with liquid as the template you provide in your question, but in azure logic app we can't.
For this requirement, I think we can just parse the json data, get the property ticket_attributes as string, remove the head "ticket_attributes": { and the tail }, and then insert it back to the resource json data.
Related
Using HubL (as I'm building a module in HubSpot), I have two arrays:
topics : Which is a list of topics.
all_tags: Which is an array of all the blog tags in the system.
If I dump out these arrays, this is what it will return:
{{ topics }} prints the following: [Data, Accounting, Insight]
{{ all_tags }} prints the following: [Accounting, Press, Data]
So essentially, {{ topics }} has a tag ("Insight") that doesn't exist in the system yet.
What I'm trying to do is to create a third array, which will contain matching results from the two above arrays. For example, topics_final, once returned, should print [Data, Accounting].
But, when printing {{ topics_final }}, the array is empty.
What I've tried:
<!-- this gets all tags -->
{% set all_tags = blog_topics( blog_id , 250) %}
<!-- create arrays -->
{% set topics = [] %}
{% set topics_final = [] %}
<!-- append topic data to the array -->
{% for item in module.add_topics.topics %}
{% set topic_option = item|striptags %}
{% do topics.append( topic_option ) %}
{% endfor %}
<!-- check if topic tags exists in HubSpot -->
{% for topics in all_tags %}
{% if topics in all_tags %}
{{ topics }}
<!-- results with above
Data, Accounting, Insight
-->
{% else %}
else
{% endif %}
{% endfor %}
With the above, it just prints out the {{ topics }}, even though Insight isn't in the all_tags array.
Note: Tagging Jinja2 as the syntax is similar
A combination of the filter reject and the built in test in could help you achieve this.
Sadly, it seems the reject filter does not accept negating a test, still, you can reject all the elements of topics that are not in all_tags then reject the said elements from the topics list.
So that ends with:
{{ topics | reject('in', topics | reject('in', all_tags) | list) | list }}
Switch yields:
[
"Data",
"Accounting"
]
I've encountered a problem regarding mapping values using liquid for a "Soap to Rest" api endpoint in API management policys.
My Example looks something like this...
The Soap Request should return something like this:
<Response>
<Truck>
<ID>098NJ2139UND324<ID>
<LicenceNumber>MKL025</LicenceNumber>
<Cargo>
<CargoLicenceNumber>BHJ897</CargoLicenceNumber>
<Cargo>Candy</Cargo>
</Cargo>
<Cargo>
<CargoLicenceNumber>TGA916</CargoLicenceNumber>
<Cargo>Fireworks</Cargo>
</Cargo>
</Truck>
</Response>
My Liquid Code sample in the "out" policy in API management looks something like this:
{
"Response": {
"id": "{{body.envelope.body.Response.ID}}",
"licencenumber": "{{body.envelope.body.Response.LicenceNumber}}",
"cargo": [
{% JSONArrayFor item in body.envelope.body.Response where Cargo -%}
{
"cargolicencenumber": "{{item.CargoLicenceNumber}}",
"cargo": "{{item.Cargo}}"
}
{% endJSONArrayFor -%}
]
}
}
But the converted XML to Json looks like this:
{
"Response":{
"ID": "098NJ2139UND324",
"LicenceNumber": "MKL025",
"Cargo": [{
"CargoLicenceNumber": "BHJ897",
"Cargo":""
},
{
"CargoLicenceNumber": "TGA916",
"Cargo":""
}
]
}
}
I'm missing this "Cargo" value in the array. I know The Setup is a bit clunky as i think the name of the array object "Cargo" should be "Trailer" or something like that (NOTE: This is an example, not the real object I'm working with). The Array having the same name as the array Sub-element is what i think is causing the problem.
As I'm not the owner of the SOAP WSDL i used to import to API management to in turn convert to a rest API, I cant easily change the name of the Array in the service. There for I'm wondering if there is a way to force liquid to find the value of the element in the array some how?
Also, worth mentioning is: as i was troubleshooting the code i changed the "{{item.Cargo}}" part to "{{item.CargoLicenceNumber}}" and that found the license plate number without any problems. So I'm thinking something in the back end is definitely getting confused by the name of the property.
Has anyone else encountered this problem before?
Thanks in advance.
It seems that the back end cannot handle xml property very well.
Based on my test, if we use xml-to-json policy and then use liquid template to handle it, the backend will be able to get the sub-element "Cargo" for you.
Here is my sample policy for your reference:
<outbound>
<base />
<xml-to-json kind="direct" apply="always" consider-accept-header="false" />
<set-body template="liquid">
{
"Response": {
"id": "{{body.Response.Truck.ID}}",
"licencenumber": "{{body.Response.Truck.LicenceNumber}}",
"cargo": [
{% JSONArrayFor item in body.Response.Truck.Cargo %}
{
"cargolicencenumber": "{{item.CargoLicenceNumber}}",
"cargo": "{{item.Cargo}}"
}
{% endJSONArrayFor %}
]
}
}
</set-body>
</outbound>
I'm trying to build a Jekyll blog. But I never used YAML before and I'm going mad with the logic of this thing.
First I wrote a YAML file in _data/authors.yml with a list of authors and their respective meta-info:
- authors:
- user: andre
name: Andre Santos
site: http://test.dev
email: andre#test.dev
- user: john
name: John Doe
site:
email: john.doe#test.dev
Now I want to do two very simple things: first, to iterate over all authors, displaying some info about them:
{% for list in site.data.authors %}
{% for author in list %}
{{ author.user }} - {{ author.user.name }}
{% endfor %}
{% endfor %}
But it shows nothing!
Now in some other part of the code I just want to retrieve info from a specific user:
{% assign the_user = site.data.authors.authors[post.username] %}
{{ the_user.name }}
And, once again it shows nothing! I have no idea what I'm doing wrong, I tried lots of other solutions, iterations, but I can't make heads or tails about how to iterate YAML files, and I don't know Ruby so most of the solutions I found in this site don't work for me when I adapt them into Jekyll + Liquid.
What am I doing wrong? How to access those variables?
Problem solved!
After some long deliberation, I got a very simple solution, based on 2 steps: change from YAML to JSON, and then understanding Jekyll returns a Ruby Hash instead of an array.
So, the final file, authors.json:
{
"andre": {
"name": "Andre Santos",
"site": "http://test.dev",
"email": "andre#test.dev"
},
"john": {
"name": "John Doe",
"site": "",
"email": "john.doe#test.dev"
}
}
Now that the file is corrected, let's take care of selecting one of its items and showing it.
{{ site.data.authors[post.author].name }}
If post.author = "andre", the template will return Andre Santos. First problem, solved!
Now, Jekyll is quite dumb and still doesn't works fine with JSON. No matter what we do, it will iterate poorly with it. So, let's analyse the following situation:
In a test, I decided to dump the iteration. So:
{% for author in site.data.author %}
{{ author }}
----
{% endfor %}
It produces the following result:
andre{"name"=>"Andre Santos", "site"=>"test.dev";, "email"=>"andre#test.dev"} ----
john{"name"=>"John Doe", "site"=>nil, "email"=>"john.doe#test.dev"} ----
This result shows Jekyll isn't producing an array, but a Hash (notice the => symbol). So, let's try to deal with it as a Hash. If I try to print {{ author[0] it will show andre and john. Excellent! So, the next part of the Hash (the metadata) is, in fact author[1].
The final code to display the info:
{% for author in site.data.authors %}
Username: {{ author[0] }}
Full Name: {{ author[1]["name"] }}
{% if author[1]["site"] != "" %}
Site: {{ author[1]["site"] }}
{% endif %}
E-Mail: {{ author[1]["email"] }}
-----
{% endfor %}
And the result:
Username: andre
Full Name: Andre Santos
Site: http://test.dev
E-Mail: andre#test.dev
----
Username: john
Full Name: John Doe
E-Mail: john.doe#test.dev
----
Ta da!
So, to wrap it up: drop YAML and use JSON, get info from a specific part of the JSON using simple dot notation and key. When using for, deal with it as a Hash. The code becomes a little harder to deal with, but at least it's working as I wanted. In the future, if Jekyll takes JSON a little more seriously, it will probably let us iterate it a little easier.
Thank you all!
You can simplify your data file :
- user: andre
name: Andre Santos
site: http://test.dev
email: andre#test.dev
- user: john
name: John Doe
site:
email: john.doe#test.dev
Now you can get your datas like this :
<ul>
{% for author in site.data.authors %}
<li>{{ author.user }} - {{ author.name }}</li>
{% endfor %}
</ul>
Or like this :
{% assign the_user = site.data.authors | where: "user", post.username | first %}
{{ the_user.name }}
I've to get access to all values availables in a list(array) in a Django template. All examples I find online, use dictionaries instead. So, the list is passed correctly to the template, but the following code doesn't work:
{% for item in array %}
field_names = field_names + "{{ item }},";
{% if forloop.last %}
field_names = field_names + "{{ item }}";
{% endif %}
{% endfor %}
I could access the values using {{ field.[0] }} , {{ field.[1] }} , etc. But, I have to make it work independently of the list's size.
Can anybody give me a hint?
P.S. - I cannot use a dictionary to pass the values to the template, since that code wasn't donne by me, and I'm not supposed to touch it.
In your view:
my_joined_list = ",".join(somelist)
In your template:
field_names = {{ my_joined_list }}
Resolved it!! I just passed the variable to the template exactly as i needed it and used {{ array|safe }} to resolve it to a Javascript variable. Done!
I am new to Twig and Symfony2 (and PHP as well). I currently have an array of objects where I can access an attribute by doing {{result.attribute1}} after a {for result in results} statement.
I would like to use a variable {{var| removePath}} (where removePath is an extension I made in Twig), and use it to iterate over the results array. What I would like to do is return the row if {{var| removePath}} == result.attribute1.
Is this possible to do in Twig? If so, how should I approach this? I have already tried something similar to the code found below, but the "else" statement is executed (saying there's no match). I also tried var == result.attribute, but this didn't work either.
{% for result in results %}
{% if var|removePath in result.attribute1 %}
{{ var | removePath }} exists.
{% else %}
{{ var | removePath }} doesn't exist in array.
{% endif %}{% endfor %}
Thus I think I have 2 questions;
1) Is it possible in TWIG (if so, how)
2) Is there an easier/better way to get the whole row (object array also contains attributes 2, 3 & 4, and I would like to return those that are in common with attribute 1 (if it matches var))
See schema of my array recently added
Thank you in advance for your help! I hope my question is understandable :S
Just surround the expression with brackets.
use (var|removePath) which groups an expression.
example:
{% if ( 1+1 ) == 2 %}
And you can use the attribute() function to access properties and methods of an object/array.
{{ attribute(object, method) }}
{{ attribute(object, method, arguments) }}
{{ attribute(array, item) }}
attribute chapter in the twig docs.
Further shorten template code using the ternary operator like this:
{% set strippedVar = var|removePath %}
{{ strippedVar }}{{ (strippedVar in result.attribute1) ? 'exists' : 'does not exist' }}.
Setting the filtered variable to another prevents executing the filter multiple times.