Graphql 在AWS AppSync中为SQL查询字符串化JSON对象

Graphql 在AWS AppSync中为SQL查询字符串化JSON对象,graphql,velocity,aws-appsync,Graphql,Velocity,Aws Appsync,问题:如何在Appsync velocity模板中为SQL语句字符串化JSON对象 解释:我有一个Aurora RDS表,它有一个数据类型为JSON的列。AppSync API已连接到RDS。 我的GraphQL模式看起来像 input CreateServiceCatalogItemInput { serviceName: String! serviceConfig: ServiceConfigInput! } type Mutation { createServic

问题:如何在Appsync velocity模板中为SQL语句字符串化JSON对象

解释:我有一个Aurora RDS表,它有一个数据类型为JSON的列。AppSync API已连接到RDS。 我的GraphQL模式看起来像

input CreateServiceCatalogItemInput {
    serviceName: String!
    serviceConfig: ServiceConfigInput!
}

type Mutation {
    createServiceCatalogItem(input: CreateServiceCatalogItemInput!): ServiceCatalogItem
}

type Query {
    getAllServiceCatalogItem: [ServiceCatalogItem]
}

type ServiceCatalogItem {
    serviceId: ID!
    serviceName: String!
    serviceConfig: ServiceConfig!
}

type ServiceConfig {
    connectionType: String
    capacity: Int
}

input ServiceConfigInput {
    connectionType: String
    capacity: Int
}

schema {
    query: Query
    mutation: Mutation
}
{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$util.toString($ctx.args.input.serviceConfig)') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
createServiceCatalogItem的解析程序如下所示

input CreateServiceCatalogItemInput {
    serviceName: String!
    serviceConfig: ServiceConfigInput!
}

type Mutation {
    createServiceCatalogItem(input: CreateServiceCatalogItemInput!): ServiceCatalogItem
}

type Query {
    getAllServiceCatalogItem: [ServiceCatalogItem]
}

type ServiceCatalogItem {
    serviceId: ID!
    serviceName: String!
    serviceConfig: ServiceConfig!
}

type ServiceConfig {
    connectionType: String
    capacity: Int
}

input ServiceConfigInput {
    connectionType: String
    capacity: Int
}

schema {
    query: Query
    mutation: Mutation
}
{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$util.toString($ctx.args.input.serviceConfig)') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
这给我带来了一个错误:

调用com.amazonaws.deepdish.transform.util.TransformUtils类中的方法“toString”引发异常java.lang.IllegalArgumentException:在…处的参数数目错误。

如果我这样做:

{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$util.toJson($ctx.args.input.serviceConfig)') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$ctx.args.input.serviceConfig') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
这给我带来了一个错误:

无法分析JSON文档:“意外字符('c'(代码99)):在…处需要逗号分隔数组项\n

如果我这样做:

{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$util.toJson($ctx.args.input.serviceConfig)') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$ctx.args.input.serviceConfig') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
然后我得到了一个有意义的错误:

RDSHttp:{“消息”:“错误:类型json的输入语法无效\n详细信息:标记\“connectionType\”无效。\n位置:222\n其中:json数据,第1行:{connectionType…”

但是,当我在解析器中硬编码JSON时,它可以工作:

{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '{\"connectionType\":\"ftth\",\"capacity\":1}') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}

那么,我如何将{connectionType=ftth,capacity=1}转换为{“connectionType”:“ftth”,“capacity”:1}?我做错了什么,还是遗漏了什么?非常感谢您的帮助。

解决方案1

多亏了@cyberwombat,我才能够解决这个问题。如果有人需要,我会将此作为参考发布

我的
serviceConfig
对象不是固定的,可能会随着时间而改变,因此我修改了我的解析器,使其更通用,它看起来像这样:

#set($serviceConfigMap = {})

#foreach($key in $ctx.args.input.serviceConfig.keySet())
    $util.qr($serviceConfigMap.put("$key", $ctx.args.input.serviceConfig.get($key)))
#end

#set($serviceConfigMap = $util.toJson($serviceConfigMap))

{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$util.escapeJavaScript($serviceConfigMap)') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
#set($json = $util.toJson({
  "connectionType": "$ctx.args.input.serviceConfig.connectionType",
  "capacity": $ctx.args.input.serviceConfig.capacity
  }))
旧解决方案

这是我以前解决这个问题的方法

我将解析器转换为管道,并在NodeJS中创建了一个简单的Lambda函数来字符串化JSON对象。我的Lambda函数如下所示:

exports.handler = (event, context, callback) => {

    const response = {
        statusCode: 200,
        body: JSON.stringify(event.input.serviceConfig).replace(/\"/g, '\\\"'),
    };
    callback(null, response)
};
这就是serviceConfig现在的样子,也是我想要的:

{\"connectionType\":\"ftth\",\"maxUploadCapacity\":1}"

现在,我可以在解析器的SQL语句中轻松地使用它。

您可以像这样构建JSON变量:

#set($serviceConfigMap = {})

#foreach($key in $ctx.args.input.serviceConfig.keySet())
    $util.qr($serviceConfigMap.put("$key", $ctx.args.input.serviceConfig.get($key)))
#end

#set($serviceConfigMap = $util.toJson($serviceConfigMap))

{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$util.escapeJavaScript($serviceConfigMap)') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
#set($json = $util.toJson({
  "connectionType": "$ctx.args.input.serviceConfig.connectionType",
  "capacity": $ctx.args.input.serviceConfig.capacity
  }))
并在查询中插入:

{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '$util.escapeJavaScript($json)' RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}
由于所有的引号和转义,上面的内容有点挑战性,但我认为使用
escapeJavaScript
就可以了

或直接:

{
    "version": "2018-05-29",
    "statements": [
        "INSERT INTO b2b_service_catalog(service_name, service_config) VALUES ('$ctx.args.input.serviceName', '{\"connectionType\":\"$ctx.args.input.serviceConfig.connectionType\",\"capacity\": $ctx.args.input.serviceConfig.capacity}') RETURNING service_id AS \"serviceId\", service_name AS \"serviceName\", service_config AS \"serviceConfig\"",
    ]
}

你是最棒的。你的解决方案成功了!!因为我的JSON不只是固定在连接类型和容量键上,所以我对你的解决方案做了一些修改。如果有人需要,我会发布我的解决方案仅供参考。非常感谢!!