Joe*_*oel 0 json jackson kotlin
我正在尝试为2个服务创建一个资源,1个在application/x-www-form-urlencoded和string payload中,另一个应用程序/ json格式用json body.
我有这个代码:
@POST @Path("/test")
fun test(@Context request: ContainerRequest): Response {
val baos = ByteArrayOutputStream()
request.entityStream.use { it.copyTo(baos) }
val ipnRawData = baos.toString()
var map : Map<String,Any>
map = when (request.headers.getFirst("Content-Type")) {
"application/json" -> objectMapper.convertValue(ipnRawData,Map::class.java) as Map<String,Any>
"application/x-www-form-urlencoded" -> LinkedHashMap()
else -> throw UnsupportedOperationException()
}
//....handle the map
return Response.status(200).build()
}
Run Code Online (Sandbox Code Playgroud)
但是当我尝试使用json选项和body :)运行它时{"name" :"test"},我收到一个错误:
"java.lang.IllegalArgumentException:无法构造java.util.LinkedHashMap的实例:no String-argument构造函数/工厂方法从String值反序列化('{"name":"test"}')"
谢谢你的帮助,Yoel
您应该使用mapper.readValue将JSON反序列化为对象.
使用原始杰克逊没有对杰克逊科特林模块:
val map: Map<String, String> = JSON.readValue("""{"name" :"test"}""",
object : TypeReference<Map<String, String>>() {})
Run Code Online (Sandbox Code Playgroud)
这传递了一个带有超类的对象表达式,TypeReference指定了您想要创建的类型,完整的泛型仍然完整(您的方法遭受类型擦除).
相反,如果您使用的是Jackson-Kotlin模块,您只需要:
val map: Map<String, String> = JSON.readValue("""{"name" :"test"}""")
Run Code Online (Sandbox Code Playgroud)
因为它有辅助/扩展功能来隐藏一些像TypeReference创建这样的丑陋的东西.
您应该始终将Jackson-Kotlin模块与Kotlin代码一起使用,以便您可以实例化任何类型的Kotlin对象,包括具有所有val参数且没有默认构造函数的数据类,使其理解可为空性,还可以处理构造函数参数的默认值.一个简单的独立示例:
import com.fasterxml.jackson.module.kotlin.*
val JSON = jacksonObjectMapper() // creates ObjectMapper() and adds Kotlin module in one step
val map: Map<String, String> = JSON.readValue("""{"name" :"test"}""")
Run Code Online (Sandbox Code Playgroud)
注意导入,.*以便它获取所有扩展函数,否则您需要显式导入: com.fasterxml.jackson.module.kotlin.readValue
或者在您的情况下,修改后的代码将是:
import com.fasterxml.jackson.module.kotlin.readValue
val objectMapper = jacksonObjectMappe() // instead of ObjectMapper()
...
@POST @Path("/test")
fun test(@Context request: ContainerRequest): Response {
val bodyAsString = request.entityStream.bufferedReader().readText()
val map: Map<String, Any> = when (request.headers.getFirst("Content-Type")) {
"application/json" -> objectMapper.readValue(bodyAsString)
"application/x-www-form-urlencoded" -> LinkedHashMap()
else -> throw UnsupportedOperationException()
}
//....handle the map
return Response.status(200).build()
}
Run Code Online (Sandbox Code Playgroud)
代码也被清理了一点,以删除a的使用,var并以更Kotlin友好的方式读取实体流.
另请注意,Content-Type标头可能更复杂,它也可能包含编码,例如:
Content-type: application/json; charset=utf-8
Run Code Online (Sandbox Code Playgroud)
因此,您可能需要一个实用程序函数来检查标头是"等于application/json还是以application/json;" 开头,而不是仅检查相等性.
最后,您可以request.entityStream直接传递给objectMapper.readValue它,并且永远不会将它复制到字符串中.有各种重载readValue可以帮助这些类型的输入.
| 归档时间: |
|
| 查看次数: |
981 次 |
| 最近记录: |