Apache VTL - Copy node - json

Is there a way to do deep copy using apache VTL?
I was trying to use x-amazon-apigateway-integration using requestTemplates.
The input JSON is as shown below,
{
"userid": "21d6523137f6",
"time": "2020-06-16T15:22:33Z",
"item": {
"UserID" : { "S": "21d6523137f6" },
<... some complex json nodes here ...>,
"TimeUTC" : { "S": "2020-06-16T15:22:33Z" },
}
}
The requestTemplate is as shown below,
requestTemplates:
application/json: !Sub
- |
#set($inputRoot = $input.path('$'))
{
"TableName": "${tableName}",
"ConditionExpression": "attribute_not_exists(TimeUTC) OR TimeUTC > :sk",
"ExpressionAttributeValues": {
":sk":{
"S": "$util.escapeJavaScript($input.path('$.time'))"
}
},
"Item": "$input.path('$.item')", <== Copy the entire item over to Item.
"ReturnValues": "ALL_OLD",
"ReturnConsumedCapacity": "INDEXES",
"ReturnItemCollectionMetrics": "SIZE"
}
- {
tableName: !Ref EventsTable
}
The problem is, the item gets copied like,
"Item": "{UserID={S=21d6523137f6}, Lat={S=37.33180957}, Lng={S=-122.03053391}, ... other json elements..., TimeUTC={S=2020-06-16T15:22:33Z}}",
As you can see, the whole nested json become a single atribute. While I expected it to become a fully blown json node on its own like below,
"Item": {
"UserID" : { "S": "21d6523137f6" },
"Lat": { "S": "37.33180957" },
"Lng": { "S": "-122.03053391" },
<.... JSON nodes ...>
"TimeUTC" : { "S": "2020-06-20T15:22:33Z" }
},
Is it possible to deep/nested copy operation on a json node like above without doing the kung-fu of iterating the node and appending the childs o a json node variable etc...
btw, I'm using AWS API Gateway request template, so it may not support all the Apache VTL templating options.

You need to use the $input.json method instead of $input.path.
"Item": $input.json('$.item'),
Note that I removed the double quotes.
If you had the double quotes because you want to stringify $.item, you can do that like so:
"Item": "$util.escapeJavaScript($input.json('$.item'))",

Related

ReactJS material-UI tableData to parse nested JSON

My client is ReactJS and server is Java Jersey based.
Java Jersey produces the following nested JSON.
[
{
"projectname": "BMI",
"testRun": "5934391890034305",
"numberOfTestcases": "3",
"timeNowString": "Mon Sep 21 21:17:34 IST 2020",
"oidobjList": [
{
"oid": "5f68cb16f01c7607230d1fcd"
},
{
"oid": "5f68cb16f01c7607230d1fcf"
},
{
"oid": "5f68cb16f01c7607230d1fd1"
}
],
"fileNameObjList": [
{
"fileName": "Basispath_BMI_0_out.gif"
},
{
"fileName": "Basispath_BMI_1_out.gif"
},
{
"fileName": "Basispath_BMI_2_out.gif"
}
]
},
{
"projectname": "BMI",
"testRun": "3320691551029718",
"numberOfTestcases": "3",
"timeNowString": "Mon Sep 21 18:37:54 IST 2020",
"oidobjList": [
{
"oid": "5f68a5aaf01ca8f40b42a4e7"
},
{
"oid": "5f68a5aaf01ca8f40b42a4e9"
},
{
"oid": "5f68a5aaf01ca8f40b42a4eb"
}
],
"fileNameObjList": [
{
"fileName": "Basispath_BMI_0_out.gif"
},
{
"fileName": "Basispath_BMI_1_out.gif"
},
{
"fileName": "Basispath_BMI_2_out.gif"
}
]
}
]
My ReactJS code is as follows:
{this.props.articles.map((el, index) => (
<Table
tableHeaderColor="primary"
tableHead={["Parameter", "Value"]}
tableData={[
["Project Name: ", el.projectname],
["Test Run: ", el.testRun],
["No Of TestCases: ", el.numberOfTestcases],
// ["File Name: ", el.fileNameObjList],
["Time Stamp: ", el.timeNowString],
]}
/>
))}
The response received in client side is attached in the image
Questions:
How to render nested JSON elements in ReactJS material-ui based tableData?
How to get filenames using map and index?
Please provide solution to this issue.
1 - First you need to decide how you will render your table. If you just want to render a single table for all your nested arrays, you can generate a single array of it and render normally. You can also render multipla tables, one for each nested array, it's your choice as a programmer.
2 - You can get filenames field by doing an simple map in fileNameObjList. But if you want a single array of filenames, you can either use Array.reduce or combine the mapped arrays with Array.concat or by pushing every item with an for loop
and also, I'm not sure but i don't think Material UI table is used that way. You may be using another data-table component that uses MUI

JsonPath filter query syntax

I'm trying to write a JsonPath query that selects a specific object based on a condition, but either the syntax fails me or I fail the syntax.
Given the below Json object, how would I select the "Data" object containing Dirk Gently's details based on the fact that he uses the "Stumble" method?
{
"Investigators": [
{
"Type": "Legend",
"Object": {
"Method": "Investigate",
"Data": {
"Name": "Sherlock",
"Surname": "Holmes"
}
}
},
{
"Type": "Visionary",
"Object": {
"Method": "Stumble",
"Data": {
"Name": "Dirk",
"Surname": "Gently"
}
}
}
],
"Version": 1
}
I know that I can get to the Method-field like this:
$.Investigators..Object.Method
I assumed that something like this would work:
$.Investigators..Object[?(#.Method=="Stumble")].Data
I'm testing this using: https://jsonpath.com/ to evaluate the query - and I can't seem to get it right.
Am I trying to do something that is not achievable or am I just making a stupid mistake?
Go to this jsonpath online sandbox and try this experssion:
$.Investigators..Object[?(#.Method=="Stumble")].Data
using either the Jayway or Gatling implementations, the output will be:
[
{
"Name" : "Dirk",
"Surname" : "Gently"
}
]

How to remove one property from json input message using replace() expression in azure logic app?

{
"metadata": {
"id": "2",
"uri": "3",
"type": "2"
},
"Number": "2323600002913",
"Date": "04/21/2009",
"postingDate": "00/00/0000",
"ata": {
"results": [
{
"metadata": {
"id": "r",
"uri": "e2",
"type": "s2"
},
"item": "000010",
"data":"ad"
}
]
}
}
want to remove metadata property from above json message and output should be like below
{
"Number": "2323600002913",
"Date": "04/21/2009",
"postingDate": "00/00/0000",
"ata": {
"results": [
{
"item": "000010",
"data":"ad"
}
]
}
}
I tried with removeProperty() which is working for root level metadata but inside metadata not removed.
how to use replace() in this case or anything else to only remove metadata.
The simplest way is use inline code, cause even with removeProperty() expression to remove the metadata under results, it will return the results array data not the whole json data. Then you will have to combine them, it's not a convenient way.
And with inline code you could refer to my below picture. The variable json is the value from triggerbody, then just delete the node or key and return the json variable. And with this way, even you want to delete many metadata in the array, you could add a for loop to delete it, just think of it as plain js code.
Update:if you want to get value from variable,cause no support expression to get value from variable so use the below expression.
var json =wworkflowContext.actions.Initialize_variable.inputs.variables[0].value;
And about how to loop the array in the json refer to my below pic.

Formatting DynamoDB data to normal JSON in API gateway

just like the question asked here
I do a query or scan operation on dynamoDB using dynamoDB proxy service on AWS API Gateway to read data for the Client and I get DynamoDB formatted JSON data in reply.
Although I can use the "Method Response" to convert but when the Data is above 1000 records - I cannot handle it due to the limitation of foreach loop in Method Response.
Is there a flag or a setting somewhere in dynamodb or in api gateway such that I get normal json rather than the dynamoDB formatted JSON ?
DynamoDB Formatted JSON example
{
"videos": [
{
"file": {
"S": "file1.mp4"
},
"id": {
"S": "1"
},
"canvas": {
"S": "This is Canvas1"
}
},
{
"file": {
"S": "main.mp4"
},
"id": {
"S": "0"
},
"canvas": {
"S": "this is a canvas"
}
}
]
}
Normal Json example of the same
{
"videos": [
{
"file": "file1.mp4",
"id": "1",
"canvas": "This is Canvas1"
},
{
"file": main.mp4",
"id": "0",
"canvas": "this is a canvas"
}
]
}
Using an Integration Response mapper!
The mapper would probably look something like: (I'm using your provided response)
#set($inputRoot = $input.path('$'))
{
"videos": [
#foreach($elem in $inputRoot.Items)
{ "file": "$elem.file.S",
"id": "$elem.id.S",
"canvas": "$elem.canvas.S" }#if($foreach.hasNext), #end
#end
]
}
Please consult the linked documentation for more complete guidance on attaching AWS Services directly to API Gateway.
The possible solution for this is using a aws lambda to query/scan dynamoDb and reply back the domain object after converting it into a json using some json lib, like GSON or jackson.
If any one has knowledge about an alternate option - please do post here. Thanks

json schema for a map of similar objects

I wish to write a json schema to cover this (simplified) example
{
"errorMessage": "",
"nbRunningQueries": 0,
"isError": False,
"result": {
"foo": {"price":10.0, "country":"UK"},
"bar": {"price":100.2, "country":"UK"}
}
}
which can have this pretty trivial root schema
schema = {
"type":"object",
"required":True,
"properties":{
"errorMessage": {"type":"string", "required":True},
"isError": {"type":"boolean", "required":True},
"nbRunningQueries": {"type":"number", "required":True},
"result": {"type":"object","required":True}
}
}
The complication is the results {} element. Unlike a standard pattern where results would be an array of same objects - each with an id field or similar this response models a python dictionary which looks like this:
{
"foo": {},
"bar": {},
...
}
So given that a will be getting a results object of flexible size with no set keys how can I write json schema for this?
I don't control the input sadly or I'd rewrite it to be something like
{
"errorMessage": "",
"nbRunningQueries": 0,
"isError": False,
"result": [
{"id": "foo", "price":10.0, "country": "UK"},
{"id": "bar", "price":100.2, "country":"UK"}
]
}
Any help or links to pertinent examples would be great. Thanks.
With json-schema draft 4, you can use additionalProperties keyword to specify the schema of any new properties that you could receive in your results object.
"result" : {
"type" : "object"
"additionalProperties" : {
"type" : "number"
}
}
If you can restrict the allowed key names, then you may use "patternProperties" keyword and a regular expression to limit the permited key names.
Note that in json-schema draft 4 "required" must be an array which is bounded to the object, not to each property.