AWS
GraphQL
AppSync

【AWS AppSync】HTTPリクエストで配列データを受け取る際のResolverについて

AWS AppSyncのデータソースとしてHTTPリクエストを使ってAPIから配列データを受け取りたいが、どうマッピングすれば良いのか分からずしばらく詰まってしまった時の備忘録。


SchemaとQuery

ECSで動いているAPIへ、userIdをキーにリクエスト投げて、Transactionオブジェクトの配列データを受け取るSchema。


Schema

type ListTransactionsResponse {

statusCode: Int!
transactions: [Transaction]
}

type Query {
listTransactions(userId: String!): ListTransactionsResponse
}

type Transaction {
transactionId: String!
transactionDate: String!
transactionType: String!
}



Query

query listTransactions {

listTransactions(userId: "123456"){
statusCode
transactions{
transactionId
transactionDate
transactionType
}
}
}


Resolver

アプリ側のレスポンスのbodyにレコードを格納しているので、アプリからのResponseの中身としてはcontext.result.bodyに欲しいデータが格納されている。


response/context

  "context": {

"arguments": {
"userId": "123456"
},
"result": {
"headers": {
"Content-Length": "496",
"Content-Type": "application/json",
"Date": "Wed, 27 Feb 2019 04:59:03 GMT",
"x-amz-apigw-id": "VvjbmG6RvHcFrpA=",
"x-amzn-RequestId": "66efd625-3a4c-11e9-8292-c1ffb3d8ffa7",
"X-Amzn-Trace-Id": "Root=1-5c761917-95fe6e504485a250d04c2da0"
},
"statusCode": 200,
"body": "{\n \"transactions\": [\n {\n \"transactionId\": 001,\n \"transactionDate\": \"2019-02-26 10:50:44\",\n \"transactionType\": \"入金\"\n },{\n \"transactionId\": 002,\n \"transactionDate\": \"2019-02-26 12:10:12\",\n \"transactionType\": \"送金\"\n },{\n \"transactionId\": 003,\n \"transactionDate\": \"2019-02-26 12:12:34\",\n \"transactionType\": \"送金\"\n }]\n}"
},
"stash": {},
"outErrors": []
},

例えばDynamoDBをデータソースに指定している場合は、凡そ以下のシンプルなマッピングで問題なかったが、今回はこのままだとQueryへのレスポンスとして正しく受け取れないため、正しいマッピングをしてあげる必要がある。

$util.toJson($ctx.result)


Queryへのレスポンスがこうなってしまう

{

"data": {
"listTransactions": {
"statusCode": 200,
"transactions": null
}
}
}

そこで、Transactionオブジェクト配列が格納されたbody部分をfor文で回しながら1レコードずつマッピングしてあげると、


response_mapping_template

#set ($bodyObj = $util.parseJson($context.result.body))

{
"statusCode": $context.result.statusCode,
"transactions": [
#foreach($transaction in $bodyObj.transactions)
{
"transactionId" : "$transaction.transactionId",
"transactionDate" : "$transaction.transactionDate",
"transactionType" : "$transaction.transactionType"
}
#if($foreach.hasNext),#end
#end
]
}

{

"data": {
"listTransactions": {
"statusCode": 200,
"transactions": [
{
"transactionId": "001",
"transactionDate" : "2019-02-26 10:50:44",
"transactionType" : "入金"
},
{
"transactionId": "002",
"transactionDate" : "2019-02-26 12:10:12",
"transactionType" : "送金"
},
{
"transactionId": "003",
"transactionDate" : "2019-02-26 12:12:34",
"transactionType" : "送金"
}
]
}
}
}

上手くいった!

要はレスポンスの中身ちゃんと意識してマッピング考えないとだめですよね、っていうお粗末な話でした。