Appsync解析器条件更新AWSJSON属性

0

【以下的问题经过翻译处理】 我有一个用于对象的修改,在其中有多个非必填字段可能在单个调用中进行更新。其中一个属性"data"在架构中被定义为AWSJSON。为了构建更新,我使用以下类似的语句来检查提供的值#if( !$util.isNull(${context.arguments.input.data}) )

如果存在属性的数据,那么必要的值将被添加到映射中,以构建最终的SET表达式,映射属性名称#data => data(对于具有保留字名称的属性是必要的),以及values :data => value

最终的更新使用$utils.toJson来应用构建的映射。问题是,当我提供AWSJSON属性的数据时,我收到以下错误: "Expected JSON object for attribute value '$[update][expressionValues][:data]' but got 'STRING' instead."

只要没有提供JSON属性,所有其他属性都可以正常工作。

然而,如果我改为内联提供expressionValues,而不是使用$utils.toJson,但也不能有条件地添加属性到更新中,它会按预期工作。我是否使用了错误的方式将收集的expressionValues映射应用于最终的更新语句,也许应该使用不同的$utils方法?还有其他解决方法来处理变化的非必填属性的集合吗?最坏的情况下,我可以为JSON属性创建一个单独的变化,但显然不是理想的方法,因为需要两次调用而不是一次。

我可以像这样从Appsync控制台进行调用:

mutation UpdateMyItem {
  updateMyItem(input: {
    id: "ITEM-ID-HERE",
    data:"[{\"xyz\": 101}]"
  }) {
    id,
    data
  }
}

解析:

{
  "version": "2017-02-28",
  "operation" : "UpdateItem",
  "key" : {
    "id" : $util.dynamodb.toDynamoDBJson($context.arguments.input.id)
  },
  ## Set up some space to keep track of things we're updating **
  #set( $expSet = {} )
  #set( $expNames = {} )
  #set( $expValues = {} )

  ## updatedAt
  #set($now = $util.time.nowISO8601())
  $!{expSet.put("updatedAt", ":updatedAt")}
  $!{expValues.put(":updatedAt", { "S" : "$now"})}

  ## data
  #if( !$util.isNull(${context.arguments.input.data}) )
    $!{expSet.put("#data", ":data")}
    $!{expNames.put("#data", "data")}
    $!{expValues.put(":data", $util.dynamodb.toDynamoDBJson($context.arguments.input.data) )}
  #end

  ## other redacted optional input arguments of various types would be here

  ## build the expression
  #set( $expression = "SET" )
  #foreach( $entry in $expSet.entrySet() )
    #set( $expression = "${expression} ${entry.key} = ${entry.value}" )
    #if ( $foreach.hasNext )
      #set( $expression = "${expression}," )
    #end
  #end

  "update" : {
    "expression": "${expression}",
    "expressionNames": $utils.toJson($expNames),
    ## this fails and results in an error: 
    ## "Expected JSON object for attribute value '$[update][expressionValues][:data]' but got 'STRING' instead."
    "expressionValues": $util.toJson( $expValues )
    ## this works and all attributes are updated
    ##"expressionValues": {
    ##  ":updatedAt" : $util.dynamodb.toDynamoDBJson($now),
    ##  ":data" : $util.dynamodb.toDynamoDBJson($context.arguments.input.data)
    ##}
  }
}
profile picture
EXPERTE
gefragt vor 6 Monaten22 Aufrufe
1 Antwort
0

【以下的回答经过翻译处理】 我支持你,你的方向是对的

$!{expValues.put(":data", $util.dynamodb.toDynamoDBJson($context.arguments.input.data) )}

$!{expValues.put(":data", $util.dynamodb.toDynamoDB($context.arguments.input.data) )}

如果您使用控制台解析器测试器按原样运行您的解析器代码,您会注意到您的代码的输出是:

...
"expressionValues": {
  ":updatedAt": { "S": "2019-07-10T20:35:30.000Z" },
  ":data": "{\"S\":\"[{\\\"xyz\\\": 101}]\"}"
}
...
...
"expressionValues": {
  ":updatedAt": { "S": "2019-07-10T20:35:30.000Z" },
  ":data": "{\"S\":\"[{\\\"xyz\\\": 101}]\"}"
}
...

您会注意到这里的区别是":updatedAt"键打印了一个DynamoDB类型的对象。(参见:<https://docs.aws.amazon.com/appsync/latest/devguide/resolver-mapping-template-reference- dynamodb.html#aws-appsync-resolver-mapping-template-reference-dynamodb-typed-values-request>),而":data"键打印了一个DynamoDB类型的对象,但作为一个字符串。这就是为什么您收到了"Expecting JSON object..."错误的原因,因为DynamoDB解析器期望一个JSON对象来指定要写入DynamoDB的值的类型。


如果您查看 DynamoDB Resolver Util 参考(参见:<https://docs.aws.amazon.com/appsync/latest/devguide/resolver-util-reference.html#dynamodb-helpers-in-util-dynamodb>) ,您会注意到`$util.dynamodb.toDynamoDBJson(Object)`方法返回一个字符串,您将其保存到`expValues`映射中,然后传递给`$util.toJson(Object)`,后者期望一个输入对象,并将其作为字符串返回,然后在vtl中打印为输出。我理解这可能会令人困惑,因为这里涉及了几个层次:您如何将值存储在`expValues`映射中,以及所有变量都必须评估为字符串,以便作为VTL的输出打印(总体上是一个字符串,用于表示DynamoDB数据源理解的JSON对象。

进一步查看解析器参考,您会看到`$util.dynamodb.toDynamoDB(Object)`方法,它返回一个Map,与您在":updatedAt"中定义的字面上的映射相同,即`{ "S": "$now" }`,这将为您提供预期的输出,将打印在`expressionValues`下。
profile picture
EXPERTE
beantwortet vor 6 Monaten

Du bist nicht angemeldet. Anmelden um eine Antwort zu veröffentlichen.

Eine gute Antwort beantwortet die Frage klar, gibt konstruktives Feedback und fördert die berufliche Weiterentwicklung des Fragenstellers.

Richtlinien für die Beantwortung von Fragen