2016-09-14 4 views
0

2つのサービスのリソースを作成しようとしています。application/x-www-form-urlencodedとstring payloadで1、json bodyで他のアプリケーション/ 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のオプション、および身体でそれを実行しようとすると:{"name" :"test"})、私はエラーを取得する:任意の助け

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

感謝を、Yoel

答えて

5

mapper.readValueを使用して、JSONをオブジェクトに逆シリアル化する必要があります。

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

これは、あなたが無傷で、まだ完全なジェネリック医薬品を作成するために欠けているタイプ(あなたの方法は、タイプに苦しんを指定するスーパークラスTypeReferenceobject expressionに渡し:なしJackson-Kotlin moduleを生ジャクソンを使用して

消去)。代わりに

、あなたは、あなただけの必要Jackson-Kotlin module使用している場合:

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

それはTypeReference作成のような醜いものの一部を非表示にするヘルパー/拡張機能を持っているために。

あなたはすべてのvalパラメータなしのデフォルトコンストラクタを持っているデータクラスを含むKotlinの任意の型のオブジェクトをインスタンス化できるように、あなたは常にそれがNULL値許容を理解し、またのデフォルト値に対処している、Kotlinコード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の使用を削除するために、よりKotlinのfriendl内のエンティティのストリームを読み取るために少しクリーンアップされていますy way。ヘッダが「application/jsonまたは開始に等しいのであれば、あなたがチェックするユーティリティ関数をすることができ

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

Content-Typeヘッダは、より複雑であってもよいし、そのようなだけでなく、エンコードが含まれる可能性があることに注意してくださいapplication/json; "を使用してください。

最後にrequest.entityStreamobjectMapper.readValueに直接渡して、まったく文字列にコピーすることはできません。これらのタイプの入力に役立つreadValueのさまざまなオーバーロードがあります。

+0

詳細な回答と役立つ情報をありがとう! – Joel

関連する問題