如何将 KotlinModule 注册到 AWS lambda Jackson Object Mapper?

dus*_*van 6 json amazon-web-services jackson kotlin aws-lambda

Kotlin用来写一个AWS Lambda. 我有一个Kotlin数据类

class MessageObject(
  val id: String,
  val name: String,
  val otherId: String
)
Run Code Online (Sandbox Code Playgroud)

此数据类用作所需接口实现的输入

class Handler : RequestHandler<MessageObject, Output> {
  ...  
  override fun handleRequest(msg: MessageObject, ctx: Context) {
    ...
  }
}
Run Code Online (Sandbox Code Playgroud)

当我在 aws 控制台中测试此 lambda 并将其传递给正确的 JSON 消息时,我得到以下信息:

An error occurred during JSON parsing: java.lang.RuntimeException
java.lang.RuntimeException: An error occurred during JSON parsing
Caused by: java.io.UncheckedIOException: 
com.amazonaws.lambda.thirdparty.com.fasterxml.jackson.databind.exc.InvalidDefinitionException:
Cannot construct instance of 'com.mycode.MessageObject'(no Creators, like default construct, exist): 
cannot deserialize from Object value (no delegate- or property-based Creator)
Run Code Online (Sandbox Code Playgroud)

我几乎可以肯定这是通过说来解决的: ObjectMapper().registerModule(KotlinModule()) 但是在AWS Lambda我如何编辑 AWS 提供的对象映射器的世界中?

Cra*_*ton 5

如果您还没有让它与 KotlinModule 一起工作,因为您遇到的问题是 Jackson 需要一个默认的空构造函数,而您目前没有。您可以按如下方式更改 MessageObject,它应该可以工作:

  data class MessageObject(
  var id: String = "",
  var name: String = "",
  var otherId: String = ""
)
Run Code Online (Sandbox Code Playgroud)

我使用无服务器框架使用功能齐全的 kotlin lambda 模板创建了这个 repo。查看您可能需要的其他一些花絮:https : //github.com/crafton/sls-aws-lambda-kotlin-gradlekt


小智 4

不幸的是,您不能使用提供的数据类RequestHandler<I, O>,因为您需要为您的 Jackson 映射器注册 kotlin 模块才能使用数据类。但是你可以编写自己的RequestHandler,它会喜欢这个。

这是代码:

interface MyRequestStreamHandler<I : Any, O : Any?> : RequestStreamHandler {
    val inputType: Class<I>

    fun handleRequest(input: I, context: Context): O?

    override fun handleRequest(inputStream: InputStream, outputStream: OutputStream, context: Context) {
        handleRequest(inputStream.readJson(inputType), context).writeJsonNullable(outputStream)
    }

    interface MessageObjectRequestHandler : MyRequestStreamHandler< MessageObject, Output> {
        override val inputType: Class<MessageObject >
            get() = MessageObject::class.java
    }
}
Run Code Online (Sandbox Code Playgroud)

和杰克逊实用程序:

private val objectMapper = jacksonObjectMapper()
        .configure(JsonParser.Feature.ALLOW_COMMENTS, true)
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .registerKotlinModule()

private val writer: ObjectWriter = objectMapper.writer()

fun <T : Any> readJson(clazz: Class<T>, stream: InputStream): T =
        objectMapper.readValue(stream, clazz)

fun <T : Any> InputStream.readJson(clazz: Class<T>): T =
        readJson(clazz, this)

fun Any?.writeJsonNullable(outputStream: OutputStream) {
    if (this != null)  writer.writeValue(outputStream, this)
}
Run Code Online (Sandbox Code Playgroud)

现在,您可以将 MessageObject 类保留为数据类,并且您的处理程序将如下所示:

class LambdaMain : MessageObjectRequestHandler {
    override fun handleRequest(input: MessageObject, context: Context): Output { 
        //...
    }
}
Run Code Online (Sandbox Code Playgroud)