Как вернуть объект JSON из DynamoDB с appsync?

Как я могу получить объект JSON в ответ от DynamoDB? Я храню данные в БД как массив объектов в формате JSON. У меня есть следующий запрос шаблона сопоставления

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
  "userId": {
    "S":  "$context.identity.username"
  }
},
  #set( $attrs = $util.dynamodb.toMapValues($ctx.args))
  #set( $attrs.categories = $util.dynamodb.toDynamoDB($ctx.args.categories))

  "attributeValues": $util.toJson($attrs)
}

и отображение шаблона ответа

#set( $result = $ctx.result)
#set( $result.categories = $util.parseJson($ctx.result.categories))
$util.toJson($result)

но я получил ответ в формате DynamoDB JSON

"createItem": {
      "title": "Test 1",
       "categories": "[{name=food, id=2}, {name=eat, id=1}]"
    }

в DynamoDB дату сохранить как

"categories": {
    "L": [
      {
        "M": {
          "id": {
            "S": "2"
          },
          "name": {
            "S": "food"
          }
        }
      },
      {
        "M": {
          "id": {
            "S": "1"
          },
          "name": {
            "S": "eat"
          }
        }
      }
    ]
  }

Как разобрать это в нормальный JSON или объект?

1 ответ

Решение

В вашем текущем шаблоне отображения вы храните категории как "S" в DDB, что означает строку, и именно поэтому вы получаете строковую версию списка DynamoDB. Предполагая, что вы запускаете мутацию, которая выглядит примерно так:

mutation {
  create(input: { title: "Test 1", categories: [{ name: "category 1" }] }) {
    title
    categories {
      name
    }
  }
}

Затем вы должны изменить свой шаблон отображения на это:

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "userId": {
      "S":  "$context.identity.username"
    }
  },
  "attributeValues": $util.toJson($ctx.args)
}

Приведенный выше шаблон можно использовать, если вы хотите сохранить данные в виде списков DynamoDB и карт. Если вы вместо этого пытаетесь сохранить свой JSON как строковый BLOB-объект JSON в атрибуте DynamoDB "S", но без L и M, тогда вместо этого измените свой шаблон следующим образом:

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "userId": {
      "S":  "$context.identity.username"
    }
  },
    #set( $attrs = $util.dynamodb.toMapValues($ctx.args))

    ## NOTE: The $util.toJson instead of the dynamodb version which adds L, M, S, etc
    #set( $attrs.categories = { "S":  "$util.toJson($ctx.args.categories)"})
    "attributeValues": $util.toJson($attrs)
}

И затем в шаблоне отображения ответов вам нужно будет проанализировать JSON, чтобы вернуть структурированный JSON вместо строковой строки JSON.

## Get the result and parse categories into structured objects.
#set( $result = $ctx.result)
#set( $result.categories = $util.parseJson($ctx.result.categories))

## Return the full JSON payload
$util.toJson($result)

РЕДАКТИРОВАТЬ (Подробнее):

У меня есть эти части схемы (обратите внимание, это не завершено):

type Category {
    name: String
}

input CategoryInput {
    name: String
}

input CreatePostInput {
    title: String
    categories: [CategoryInput]
}

type Post {
    id: ID!
    title: String
    categories: [Category]
}

type Mutation {
    createPost(input: CreatePostInput!): Post
}

И этот шаблон отображения запроса точно:

## Mutation.createPost request mapping template
#set( $attrs = $util.dynamodb.toMapValues($ctx.args.input))
#set( $attrs.categories = { "S":  "$util.toJson($ctx.args.input.categories)"})

{
  "version": "2017-02-28",
  "operation": "PutItem",
  "key": {
    "id": $util.dynamodb.toDynamoDBJson($util.autoId()),
  },
  "attributeValues": $util.toJson($attrs),
  "condition": {
    "expression": "attribute_not_exists(#id)",
    "expressionNames": {
      "#id": "id",
    },
  },
}

И этот шаблон отображения ответа

## Mutation.createPost response mapping template
## Get the result and parse categories into structured objects.
#set( $result = $ctx.result)
#set( $result.categories = $util.parseJson($ctx.result.categories))

## Return the full JSON payload
$util.toJson($result)

Затем я смог выполнить этот запрос:

mutation {
  createPost(input: {
    title: "Hello, world!",
    categories: [
      {
        name: "cat1"
      }
    ]
  }) {
    id
    title
    categories {
      name
    }
  }
}

и получил этот ответ:

{
  "data": {
    "createJSONTest2": {
      "id": "c72ff226-0d67-41c4-9c47-784955a64bc5",
      "title": "Hello, world!",
      "categories": [
        {
          "name": "cat1"
        }
      ]
    }
  }
}

когда я иду на консоль DynamoDB это сохраняется как атрибут категории

[{"name":"cat1"}]

Похоже, это все работает правильно. Lmk, если вам нужна дополнительная помощь в отладке.

Другие вопросы по тегам