2

I have an appsync velocity response mapping template that is returning the annoying error of

"Unable to convert \n          \n           ,           \n       ,           \n  \n\n{\"channels\":[{\"createdAt\":\"2020-09-01T14:25:32.796Z\",\"featured\":false,\"thumb\":\"http://www.google.com\",\"__typename\":\"Channel\",\"description\":\"The test channel\",\"id\":\"73bf0ef9-2d91-4b78-90f8-7548444fdb8f\",\"title\":\"The test title\",\"notifications\":false,\"tags\":[\"awesome\",\"action\"],\"updatedAt\":\"2020-09-01T14:25:32.796Z\"}],\"creators\":[],\"shows\":[{\"createdAt\":\"2020-09-01T14:40:46.996Z\",\"thumb\":\"http://www.google.com\",\"author\":\"Steven Colbert\",\"__typename\":\"Show\",\"description\":\"The tonight show with Steven Colbert\",\"id\":\"5a95234e-6d30-4396-bc05-b607eb4276f6\",\"source\":\"http://google.com\",\"title\":\"The tonight show\",\"channelId\":\"dce40626-76ae-45ba-97a9-a2b29d2234c9\",\"live\":false,\"tags\":[\"Tonight show\"],\"updatedAt\":\"2020-09-01T14:40:46.996Z\"},{\"createdAt\":\"2020-09-01T14:46:40.406Z\",\"thumb\":\"http://www.google.com\",\"author\":\"Seth Miers\",\"__typename\":\"Show\",\"description\":\"The Late show with Seth Miers\",\"id\":\"09d3d573-8737-411c-ae82-ee3600565e04\",\"source\":\"http://google.com\",\"title\":\"The Late show\",\"channelId\":\"dce40626-76ae-45ba-97a9-a2b29d2234c9\",\"live\":false,\"tags\":[\"Late show\"],\"updatedAt\":\"2020-09-01T14:46:40.406Z\"}]}\n to Object."

I do not understand why this is happening? The object seems to be correct and the graphQl schema is expecting an object with three properties, each of which should contain an array of objects.

I have checked the logs from elasticsearch request, and the response sent from the request template is correct. This is the object I get from elasticsearch:

{
    "logType": "ResponseMapping",
    "path": [
        "search"
    ],
    "fieldName": "search",
    "requestId": "c8946f14-8bb7-46a8-a23f-4b2defc0a9cd",
    "context": {
        "arguments": {
            "filter": {
                "title": {
                    "contains": "The"
                }
            }
        },
        "result": {
            "took": 36,
            "timed_out": false,
            "_shards": {
                "total": 11,
                "successful": 11,
                "skipped": 1,
                "failed": 0
            },
            "hits": {
                "total": {
                    "value": 3,
                    "relation": "eq"
                },
                "hits": [
                    {
                        "_index": "channel",
                        "_type": "_doc",
                        "_id": "73bf0ef9-2d91-4b78-90f8-7548444fdb8f",
                        "_score": 0,
                        "_source": {
                            "createdAt": "2020-09-01T14:25:32.796Z",
                            "featured": false,
                            "thumb": "http://www.google.com",
                            "__typename": "Channel",
                            "description": "The test channel",
                            "id": "73bf0ef9-2d91-4b78-90f8-7548444fdb8f",
                            "title": "The test title",
                            "notifications": false,
                            "tags": [
                                "awesome",
                                "action"
                            ],
                            "updatedAt": "2020-09-01T14:25:32.796Z"
                        },
                        "sort": [
                            "channel",
                            0
                        ]
                    },
                    {
                        "_index": "show",
                        "_type": "_doc",
                        "_id": "5a95234e-6d30-4396-bc05-b607eb4276f6",
                        "_score": 0,
                        "_source": {
                            "createdAt": "2020-09-01T14:40:46.996Z",
                            "thumb": "http://www.google.com",
                            "author": "Steven Colbert",
                            "__typename": "Show",
                            "description": "The tonight show with Steven Colbert",
                            "id": "5a95234e-6d30-4396-bc05-b607eb4276f6",
                            "source": "http://google.com",
                            "title": "The tonight show",
                            "channelId": "dce40626-76ae-45ba-97a9-a2b29d2234c9",
                            "live": false,
                            "tags": [
                                "Tonight show"
                            ],
                            "updatedAt": "2020-09-01T14:40:46.996Z"
                        },
                        "sort": [
                            "show",
                            0
                        ]
                    },
                    {
                        "_index": "show",
                        "_type": "_doc",
                        "_id": "09d3d573-8737-411c-ae82-ee3600565e04",
                        "_score": 0,
                        "_source": {
                            "createdAt": "2020-09-01T14:46:40.406Z",
                            "thumb": "http://www.google.com",
                            "author": "Seth Miers",
                            "__typename": "Show",
                            "description": "The Late show with Seth Miers",
                            "id": "09d3d573-8737-411c-ae82-ee3600565e04",
                            "source": "http://google.com",
                            "title": "The Late show",
                            "channelId": "dce40626-76ae-45ba-97a9-a2b29d2234c9",
                            "live": false,
                            "tags": [
                                "Late show"
                            ],
                            "updatedAt": "2020-09-01T14:46:40.406Z"
                        },
                        "sort": [
                            "show",
                            0
                        ]
                    }
                ]
            }
        },
        "stash": {},
        "outErrors": []
    },
    "fieldInError": false,
    "errors": [],
    "parentType": "Query"
}

This is my response mapping template. I am not a fan of or at ease with VTL templating, but I don't understand why it's complaining it cannot convert what seems to be a valid object into an object.

        #set( $channels = [] )
        #set( $creators = [] )
        #set( $shows = [] )

        #foreach($entry in $context.result.hits.hits)
          ## $velocityCount starts at 1 and increments with the #foreach loop **
          #if( $velocityCount > 1 ) , #end
          #set ($item = $entry.get("_source"))
          #set ($itemType = $entry.get("_index"))
          #if ($itemType == "channel")
            $util.qr($channels.add($item))
          #end
          #if ($itemType == "creator")
            $util.qr($creators.add($item))
          #end
          #if ($itemType == "show")
            $util.qr($shows.add($item))
          #end
        #end

        #set ($response = { "channels": $channels,"creators": $creators,"shows": $shows } )

        $util.toJson($response)

I have also tried this with the same result and error:

#set( $channels = [] )
#set( $creators = [] )
#set( $shows = [] )
#set( $hits = $context.result.hits.hits )
#set ($response = {} )

#foreach($entry in $hits)
  ## $velocityCount starts at 1 and increments with the #foreach loop **
  #if( $velocityCount > 1 ) , #end
  #set ($item = $entry.get("_source") )
  #set ($itemType = $entry.get("_index") )
  #if ($itemType == "channel")
    $util.qr( $channels.add($item) )
  #end
  #if ($itemType == "creator")
    $util.qr( $creators.add($item) )
  #end
  #if ($itemType == "show")
    $util.qr( $shows.add($item) )
  #end
#end

$util.qr($response.put("channels", $channels))
$util.qr($response.put("creators", $creators))
$util.qr($response.put("shows", $shows))

$util.toJson($response)

Relevant parts of my graphQl Schema:

type Query @aws_api_key
@aws_iam {
    search(filter: SearchFilterInput, size: Int, from: Int): SearchFilterConnectionModel
}

input SearchFilterInput {
    title: ModelStringFilterInput
    tag: ModelStringFilterInput
    userName: String
}

type SearchFilterConnectionModel @aws_api_key
@aws_iam {
    channels: [Channel]
    shows: [ListShowConnectionModel]
    creators: [Creator]
}

type ListShowConnectionModel @aws_api_key
@aws_iam {
    id: ID!
    createdAt: String
    updatedAt: String
    description: String
    source: String
    author: String
    thumb: String
    title: String
    tags: [String!]
    live: Boolean
    channelId: String
}

type Channel @aws_api_key
@aws_iam {
    id: ID!
    createdAt: String
    updatedAt: String
    tags: [String!]
    title: String
    description: String
    thumb: String
    featured: Boolean
    notifications: Boolean
}

type Creator @aws_api_key
@aws_iam {
    id: ID!
    createdAt: String
    updatedAt: String
    cognitoSub: String
    userName: String
    thumb: String
    bio: String
    channelsOwned: [ChannelsListModel!]
    showsOwned: [ShowsListModel!]
}

hyprstack
  • 4,043
  • 6
  • 46
  • 89

2 Answers2

0

I was able to reproduce the error you are getting and I think the problem is with your foreach statement where you are accessing hits twice.

Here's how it works as expected and perfectly fine:

#set( $channels = [] )
#set( $creators = [] )
#set( $shows = [] )

#set( $testCtx = [{"_source" : {"createdAt":"2020-09-01T14:25:32.796Z","featured":false,"thumb":"http://www.google.com","__typename":"Channel","description":"The test channel","id":"73bf0ef9-2d91-4b78-90f8-7548444fdb8f","title":"The test title","notifications":false,"tags":["awesome","action"],"updatedAt":"2020-09-01T14:25:32.796Z"}, "_index": "channel"}] )

#foreach($entry in $testCtx)
  ## $velocityCount starts at 1 and increments with the #foreach loop **
  #if( $velocityCount > 1 ) , #end
  #set ($item = $entry.get("_source"))
  #set ($itemType = $entry.get("_index"))
  #if ($itemType == "channel")
    $util.qr($channels.add($item))
  #end
  #if ($itemType == "creator")
    $util.qr($creators.add($item))
  #end
  #if ($itemType == "show")
    $util.qr($shows.add($item))
  #end
#end

#set ($response = { "channels": $channels,"creators": $creators,"shows": $shows } )

$util.toJson($response)

And if I change foreach statement to #foreach($entry in $testCtx[0]), I get the same stupid Unable to convert error as you are getting. Other than that, I have tested your code several time and it works perfectly fine.

I hope this will help you or at least give you some direction to point out the problem.

Myz
  • 818
  • 1
  • 8
  • 21
  • Regarding your comment about the for loop and accessing hits.hits one times to many, I've added the response I'm getting from elasticsearch to my question. – hyprstack Sep 02 '20 at 06:32
0

Figured it out in the end.

It's the line in the foreach loop

#if( $velocityCount > 1 ) , #end

this was adding , to the list of items returned, making the response an invalid json

hyprstack
  • 4,043
  • 6
  • 46
  • 89