Feature Request: Velocity Macros

0

It has been mentioned several times in this forum over the years that APIG's implementation of Velocity does not appear to support velocimacros.

This is a real shame, and I just wanted to raise it again, that this would be an absolute boon.

My use case:

  • API Gateway resources as a proxy for DynamoDB
  • Integration response mapping template defined to map arbitrary DynamoDB response to JSON

The template I have so far is:

##NOTE This template only works for Dynamos' primitive data types
##because AWS hasn't enabled velocimacros FFS
#set($root=$input.path('$').Item)
    {
        #foreach ($mapEntry in $root.entrySet())
                #set ($value=$mapEntry.value.entrySet().iterator().next().value)
                #set ($valueType=$mapEntry.value.entrySet().iterator().next().key)
                #if($valueType=="N" || $valueType=="BOOL")
                    "$mapEntry.key":$value
                #elseif($valueType=="S" || $valueType=="B")
                    "$mapEntry.key":"$value"
                #elseif($valueType=="SS" || $valueType=="BS")
                    "$mapEntry.key":[
                    #foreach ($setEntry in $value)
                        "$setEntry"
                        #if($foreach.hasNext),#end
                    #end
                    ]
                #elseif ($valueType=="NS")
                    "$mapEntry.key":[
                    #foreach ($setEntry in $value)
                        $setEntry
                        #if($foreach.hasNext),#end
                    #end
                    ]
                #end
                #if($foreach.hasNext),#end
        #end
    }

Which deals perfectly well with the primitive datatypes in DynamoDB, but in order to handle nested structures (e.g. one field is a list (L) or mapping (M)), this template would need to rely on a macro for dealing with the recursive nature of the data.

P.S. To anyone finding this post as a result of facing this or a similar issue. Just know, you're not alone, the struggle is real, and AWS have been ignoring this for years.

asked 7 years ago514 views
6 Answers
0

Please, please, Amazon, implement velocimacros! It would make so many things so much easier. Otherwise, if I want to define a custom function, I have to instead use #evaluate or #define which is really inconvenient and doesn't provide the same level of functionality.

answered 7 years ago
0

Just coming back to say I'm building another endpoint on Dynamo, and I still can't use macros.

This is leading to me having to write smelly code.

SORT IT OUT AWS!!!!!

answered 7 years ago
0

Another +1 to the ability to support Macros in VTL mappings.

Another option would be to make/enable a VLT tool/util method to change the Low level DynamoDB Response/Requests to Plain JSON the same way the DocumentClient Does in the SDKs or you can in the Console when you do create Item. This really would be a significant usability improvement.

answered 6 years ago
0

Another +1 to the ability to support Macros in VTL mappings

Please add this feature 🙏

answered 6 years ago
0

I second the call for better usability for the templates. Velocity is not a great choice, but since its there feature parity with Velocity 1.7 would be nice. Also, I ended up running Velocity in my test suite, but since the features don't match those tests will be non-conclusive.

Edited by: torgeir on Nov 4, 2019 10:37 AM

answered 6 years ago
0

Still in 2021, waiting for Velocity Macros in AWS API Gateway.
In case any one wondering, this is the macro I want to run; https://gist.github.com/narenranjit/1672345#gistcomment-2096494

#set ( $obj = '' ) ## dummy object
#set ( $int_class = $obj.class.forName('java.lang.Number') )
#set ( $bool_class = $obj.class.forName('java.lang.Boolean') )
#set ( $string_class = $obj.class.forName('java.lang.String') )
#set ( $map_class = $obj.class.forName('java.util.Map') )
#set ( $list_class = $obj.class.forName('java.util.List') )
#set ( $foreachCount = 10 )

#macro(VelListToJSON $list )
#set($myList = $list )## dereference
{
#foreach($key in $myList.keySet())
"$key":
#set($x = $myList.get($key))
#VelToJSON($x)
#if($foreachCount != $myList.keySet().size()) , #end
#end
}
#end

#macro(VelArrayToJSON $arr)
#set($myArr = $arr)
[
#foreach($x in $myArr)
#VelToJSON($x)
#if($foreachCount != $myArr.size()) , #end
#end
]
#end

#macro(VelToJSON $item)
#if($map_class.isAssignableFrom($item.class))
#VelListToJSON($item)
#elseif($list_class.isAssignableFrom($item.class))
#VelArrayToJSON($item)
#elseif($bool_class.isAssignableFrom($item.class)|| $int_class.isAssignableFrom($item.class))
$item
#else ## $string_class.isAssignableFrom($item.class)
"$item"
#end
#end

Edited by: crowdblink on Mar 23, 2021 12:00 PM

answered 4 years ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions