6

I'm quite new to AppSync (and GraphQL), in general, but I'm running into a strange issue when hooking up resolvers to our DynamoDB tables. Specifically, we have a nested Map structure for one of our item's attributes that is arbitrarily constructed (its complexity and form depends on the type of parent item) — a little something like this:

"item" : {
    "name": "something",
    "country": "somewhere",
    "data" : {
        "nest-level-1a": {
            "attr1a" : "foo",
            "attr1b" : "bar",
            "nest-level-2" : {
                "attr2a": "something else",
                "attr2b": [
                    "some list element",
                    "and another, for good measure"
                ]
            }
        }
    },
    "cardType": "someType"
}

Our accompanying GraphQL type is the following:

type Item {
    name: String!
    country: String!
    cardType: String!
    data: AWSJSON!  ## note: it was originally String!
}

When we query the item we get the following response:

{
    "data": {
        "genericItemQuery": {
            "name": "info/en/usa/bra/visa",
            "country": "USA:BRA",
            "cardType": "visa",
            "data": "{\"tourist\":{\"reqs\":{\"sourceURL\":\"https://travel.state.gov/content/passports/en/country/brazil.html\",\"visaFree\":false,\"type\":\"eVisa required\",\"stayLimit\":\"30 days from date of entry\"},\"pages\":\"One page per stamp required\"}}"
}}}

The problem is we can't seem to get the Item.data field resolver to return a JSON object (even when we attach a separate field-level resolver to it on top of the general Query resolver). It always returns a String and, weirdly, if we change the expected field type to String!, the response will replace all : in data with =. We've tried everything with our response resolvers, including suggestions like How return JSON object from DynamoDB with appsync?, but we're completely stuck at this point.

Our current response resolver for our query has been reverted back to the standard response after none of the suggestions in the aforementioned post worked:

## 'Before' response mapping template on genericItemQuery query; same result as the 'After' listed below **
#set($result = $ctx.result)
#set($result.data = $util.parseJson($ctx.result.data))
$util.toJson($result)

## 'After' response mapping template **
$util.toJson($ctx.result)

We're trying to avoid a situation where we need to include supporting types for each nest level in data (since it changes based on parent Item type and in cases like the example I gave it can have three or four tiers), and we thought changing the schema type to AWSJSON! would do the trick. I'm beginning to worry there's no way to get around rebuilding our base schema, though. Any suggestions to the contrary would be helpful!

P.S. I've noticed in the CloudWatch logs that the appropriate JSON response exists under the context.result.data response field, but somehow there's the following transformedTemplate (which, again, I find very unusual considering we're not applying any mapping template except to transform the result into valid JSON):

"arn": ...
"transformedTemplate": "{data={tourist={reqs={sourceURL=https://travel.state.gov/content/passports/en/country/brazil.html, visaFree=false, type=eVisa required, stayLimit=30 days from date of entry}, pages=One page per stamp required}}, resIds=USA:BRA, cardType=visa, id=info/en/usa/bra/visa}",
"context": ...

Apologies for the lengthy question, but I'm stumped.

  • Did you originally create the Item when `Item.data` was still a `String!`? – Lisa M Shon Aug 13 '18 at 05:39
  • Im running into this exact issue, did you figure out anything? – Munib Jun 14 '19 at 21:42
  • 1
    Do not expect to see a JSON object in GraphQL response for a AWSJSON type. GraphQL will return JSON object only for types that you declared in the schema. For AWSJSON type it will return a String that will contain an escaped JSON. – Rustem Zinnatullin Jul 03 '20 at 08:12

2 Answers2

3

AWSJSON is a JSON string type so you will always get back a string value (this is what your type definition must adhere to).

mixja
  • 6,977
  • 3
  • 32
  • 34
0

You could try to make a type for data field which contains all possible fields and then resolve fields to a corresponding to a parent type or alternatively you could try to implement graphQL interfaces

AlpacaGoesCrazy
  • 796
  • 8
  • 14