2016-09-14 5 views
0

2 개의 서비스, 1 application/x-www-form-urlencoded 및 string payload 및 json 본문이있는 다른 application/json 형식의 리소스를 만들려고합니다.ByteArrayOutputStream을 kotlin의 json으로 변환합니다.

이 코드가 있습니다

@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() 
} 

을하지만이 JSON 옵션을 실행하려고하고, 신체 때 어떤 도움

"java.lang.IllegalArgumentException: Can not construct instance of java.util.LinkedHashMap: no String-argument constructor/factory method to deserialize from String value ('{ "name" :"test"}')"

감사 : {"name" :"test"}), 오류가 발생합니다 , Yoel

답변

5

mapper.readValue을 사용하여 JSON을 객체로 역 직렬화해야합니다. 원시 잭슨 사용

Jackson-Kotlin module없이 :

이 지정하는 슈퍼 클래스 TypeReference와 함께 object expression에 전달
val map: Map<String, String> = JSON.readValue("""{"name" :"test"}""", 
         object : TypeReference<Map<String, String>>() {}) 

당신은 여전히 ​​그대로 전체 제네릭 생성하고자하는 유형 (당신이 방법은 유형을 앓고 지워 없앰). 당신 를 사용하는 경우

대신,이 Jackson-Kotlin module 만 필요합니다

val map: Map<String, String> = JSON.readValue("""{"name" :"test"}""") 

을가 TypeReference 생성과 같은 추악한 것들의 일부를 숨길 도우미/확장 기능을 가지고 있기 때문에.

당신은 항상 Null 허용을 이해하고, 또한 기본 값에 대한 처리, 그래서 모든 val 매개 변수없이 기본 생성자가 데이터 클래스를 포함하여 코 틀린 객체의 모든 유형을 인스턴스화 할 수있는 코 틀린 코드Jackson-Kotlin module를 사용한다 생성자 매개 변수. 간단한 독립형 예 :

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"}""") 

공지 사항 가져 오기 .*이 때문에 모든 확장 기능을, 그렇지 않으면 당신이 명시 적으로 가져올 필요가 집어 들고 있음 :

또는 귀하의 경우 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() 
} 

코드는 또한 var의 사용을 제거하고 더 코 틀린의 friendl의 실체 스트림을 읽을 조금 정리하고있다 y 방법.

는 또한 Content-Type 헤더가 더 복잡 할 수 있습니다, 그것은 인코딩을 포함 할 수뿐만 아니라 같은 : 헤더가 "application/json 또는 시작 동일한 경우

Content-type: application/json; charset=utf-8 

그래서 당신이 확인하는 유틸리티 기능을 할 수 있습니다 application/json; "으로 표시됩니다.

마지막으로 request.entityStreamobjectMapper.readValue에 직접 전달할 수 있으며 문자열에 전혀 복사하지 않을 수 있습니다.이러한 유형의 입력에 유용한 다양한 오버로드가 readValue입니다.

+0

자세한 답변과 유용한 정보를 보내 주셔서 감사합니다. – Joel

관련 문제