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>
Related
I have this JSON code:
{
"Subscribers": [
{
"EmailAddress":"yikes#to.com",
"CustomFields": [
],
"Lists": [
200575230
]
}
]
}
I tested it on Postaman, it works - it should push email address of every new registered user to the Campaigner.
But, for automation I use WP automator webhooks in Wordpress. For creation of this automation I can't use this above code, but code formatted per Automator "syntax".
In Automator, for example - this code below:
data": {
"customer": 123,
"first_name": "AutomatorWP",
}
Is mapped like this:
data/customer
data/first_name
And for the brackets - "The brackets ([]) place the information inside an array, so you need to place the array index like “data/0/first_name” to use this “first_name” parameter on tags." - Documentation
Does anyone knows or can figure out how to above first code "translate" to this Automator layout?
I tried with:
Subscriber/EmailAddress and Subscriber/0/EmailAddress - but I can't figure out how to send email to the right list, as simple as it is in clean JSON code
Any help appreciated
I tried any possible variation, always same error: Invalid Payload
I don't have any idea anymore, so maybe somebody worked earlier with this Automator "syntax"
I'm building a logic app that pulls some JSON data from a REST API, parses it with the Parse JSON block, and pushes it to Azure Log Analytics. The main problem I'm hitting is an important JSON field can either be an object or null. Per this post I changed the relevant part of my JSON schema to something like this
"entity": {"type": ["object", "null"] }
While this works, I'm now no longer to access entity later in the logic app as dynamic content. I can access all other fields parsed by the Parse JSON block downstream in the logic (that don't have nullable field). If I remove the "null" option and just have the type set to object, I can access entity in dynamic content once again. Does anyone know why this might be happening and/or how to access the entity field downstream?
Through the test, if we use "entity": {"type": ["object", "null"] }, we really cannot directly select entity in dynamic content.
But we can use the following expression to get the entity:
body('Parse_JSON')?['entity']
The test results seem to be no problem:
For a better understanding, let me cite a few more examples:
1. If your json is like this:
{
"entity": {
"testKey": "testValue"
}
}
Your expression is like this:
body('Parse_JSON')?['entity']
2. If your json is like this:
{
"test": {
"entity": {
"testKey": "testValue"
}
}
}
Your expression should like this:
body('Parse_JSON')?['test']?['entity']
Is there a way to filter the columns I'm getting from CDS in a Logic App, something similar to SELECT Column1, Column2 FROM table instead of SELECT * FROM table.
I have tried $select=Column1,Column2 in Filter Query without any success.
===== UPDATE =====
I'm dealing with large amounts of data and I'm trying to avoid getting throttled(Logic App Content throughput limit per 5 minutes: 600MB). Filtering out all the unnecessary fields means the Logic App will get only KB of data from CDS instead of hundreds of MB
For your requirement, I think it is difficult to implement if we just use a common action in logic app. But if we use liquid template, it will be easy, please refer to the steps I provdied below:
1. You need to create an integration account in your azure portal (I think "Free" pricing tier is enough)
2. In my logic app, I use "List records" action to get data from CDS. My data show like below:
{
"#odata.context": "https://logic-apis-eastasia.azure-apim.net/apim/commondataservice/xxxxxxxxxx/$metadata#datasets('orgd46a4820.crm')/tables('activitypointers')/items",
"value": [
{
"#odata.id": "xxxxxxxxxx",
"#odata.etag": "",
"ItemInternalId": "xxxxxxxxxx",
"statecode": 1,
"_statecode_label": "Completed",
.......
},
{
"#odata.id": "xxxxxxxxxx",
"#odata.etag": "",
"ItemInternalId": "xxxxxxxxxx",
"statecode": 1,
"_statecode_label": "Completed",
.......
},
.....
]
}
For example, I just want two columns(ItemInternalId and statecode) of the data as your requirement.
To implement the requirment get two columns(ItemInternalId and statecode) of the data, we need to write a liquid template. The code show as below:
{
"value": [
{% for item in content %}
{
"ItemInternalId": "{{item.ItemInternalId}}",
"statecode":"{{item.statecode}}"
},
{% endfor %}
]
}
Please save the liquid template in local with .liquid as its suffix (such as map.liquid).
3. Go to your integration account and click "Maps".
Then click "Add" and upload the map.liquid to integration account.
4. Go to your logic app and click "Workflow settings" tab and choose the integration account which we created just now.
5. In your logic app designer, add a "Transform json to json" action. Use the value from "List records" as the "Content" box and choose the map which we upload to integration account.
6. Run the logic app, we can see the result show as below (contains only two columns).
====================================Update================================
After "List records" action, we can use a "Parse JSON" action to parse the value from "List records".
Then use "Select" action to select the columns which you want.
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.
I am using #RepositoryRestResource annotation to expose Spring JPA Data as restful service. It works great. However I am struggling with referencing specific entity within angular app.
As known, Spring Data Rest doesn't serialise #Id of the entity, but HAL response contains links to entities (_links.self, _embedded.projects[]._links.self) like in the following example:
{
"_links": {
"self": {
"href": "http://localhost:8080/api/projects{?page,size,sort}",
"templated": true
}
},
"_embedded": {
"projects": [
{
"name": "Sample Project",
"description": "lorem ipsum",
"_links": {
"self": {
"href": "http://localhost:8080/api/projects/1f888ada-2c90-48bc-abbe-762d27842124"
}
}
},
...
My Angular application requires to put kind of reference to specific project entity in the URL, like http://localhost/angular-app/#/projects/{id}. I don't think using href is good idea. UUID (#Id) seems to be better but is not explicitly listed as a field. This is point I got stuck. After reading tons of articles I came up with 2 ideas, but I don't consider neither of those as a perfect one:
Idea 1:
Enable explicitly serialisation of #Id field and just use it to reference to the object.
Caveat: exposing database specific innards to front-end.
Idea 2:
Keep #Id field internal and create an extra "business identifier" field which can be used to identify specific object.
Caveat: Extra field in table (wasting space).
I would appreciate your comment on this. Maybe I am just unnecessarily too reserved to implement either of presented ideas, maybe there is a better one.
To give you another option, there is a special wrapper for Angular+Spring Data Rest that could probably help you out:
https://github.com/guylabs/angular-spring-data-rest