2016-09-07 21 views
0

私はJson文字列をタイプOperationResult<String>のオブジェクトに、KotlinでJacksonを使用して逆シリアル化しようとしています。タイプ名からクラス名を取得するにはどうすればよいですか?

は、私はそうのようなタイプのオブジェクトを作成する必要があります。

val mapper : ObjectMapper = ObjectMapper(); 
val type : JavaType = mapper.getTypeFactory() 
     .constructParametricType(*/ class of OperationResult */,, 
      /* class of String */); 
val result : OperationResult<String> = mapper.readValue(
        responseString, type); 

は、私は次のことを試してみたが、彼らは動作しません。

val type : JavaType = mapper.getTypeFactory() 
      .constructParametricType(
      javaClass<OperationResult>, 
      javaClass<String>); // Unresolved javaClass<T> 

val type : JavaType = mapper.getTypeFactory() 
      .constructParametricType(
      OperationResult::class, 
      String::class); 

タイプ名からJavaクラスを取得するにはどうすればよいですか?

+2

あなたはJackson-Kotilnモジュールを使用している必要があります。 https://github.com/FasterXML/jackson-module-kotlin –

+0

@JaysonMinardありがとうございました。私はMavenを使ってそれをダウンロードし、そこからjarファイルを作成しました。今後もそれを使用していきます。 –

+2

Maven Centralにアーティファクトがあり、構築する必要はありません... https://mvnrepository.com/artifact/com.fasterxml.jackson.module/jackson-module-kotlin/2.8.2 –

答えて

3

予想通り、次の作品:

val type = mapper.typeFactory.constructParametricType(OperationalResult::class.java, String::class.java) 
val operationalResult = mapper.readValue<OperationalResult<String>>("""{"result":"stack"}""", type) 
println(operationalResult.result) // -> stack 

シンプルな代替com.fasterxml.jackson.core.type.TypeReferenceを使用してジェネリック型をデシリアライズする:

val operationalResult = mapper.readValue<OperationalResult<Double>>("""{"result":"5.5"}""", 
     object : TypeReference<OperationalResult<Double>>() {}) 
println(operationalResult.result) // -> 5.5 

そしてjackson-kotlin-moduleの助けを借りて

は、あなたも書き込むことができます。

val operationalResult = mapper.readValue<OperationalResult<Long>>("""{"result":"5"}""") 
println(operationalResult.result) 
+0

多くのありがとう。私が使用しているEclipseのKotlinプラグインは、 'TypeReference'型を解決しません。また、あなたが参照したいタイプがどこに属しているかを知る上で、知覚はほとんどない。それを得るためにインポートする必要のあるパッケージを教えてください。 –

+0

@ WaterCoolerv2更新を参照してください。 – miensol

+0

多くのおかげさまです。 :-) –

2

のインスタンスを取得する必要がありますはKClassではありません。それを得るには::classの代わりに::class.javaを使用するだけです。

val type : JavaType = mapper.typeFactory.constructParametricType(OperationResult::class.java, String::class.java) 
+0

ありがとうございます。私も実際にそれを試してみましたが、Intellisenseは 'OperationResult :: class.'と入力すると提案を提案しません。私はそれがkotlin反射アセンブリを読み込むことができないという点でEclipse用のKotlinプラグインの問題であると信じています。しかし、私は確信が持てません。私はIDEをIntelliJ IDEA Ultimateに切り替えています。あなたが提案したソリューションがうまくいくかどうかを報告します。再度、感謝します。 :-) –

+0

でも、無料バージョン(Intellij IDEA Community)はKotlinでうまくいきます:) – rafal

+0

あなたは正しいですが、私はサーブレットを書いていますが、Community Editionではサポートしていません。 http://stackoverflow.com/q/39072303/303685 –

4

Kotlinには、Jackson、GSON、またはKotlinオブジェクトをインスタンス化する他のライブラリを使用する際に問題となるものがいくつかあります。一つは、ClassTypeTokenTypeReference、またはいくつかの図書館が知りたい他の専門クラスをどうやって得るかです。もう一つは、常にデフォルトコンストラクタを持たないクラス、または不変であるクラスをどのように構築できるかです。

ジャクソンの場合、モジュールはこれらのケースをカバーするために特別に作成されました。それは@ miensolの答えに言及されています。インライン関数に利用できる(これは実際KotlinモジュールによってObjectMapperに添加インライン拡張機能を呼び出して、それが具体化ジェネリックをつかん結果の推論型を使用

import com.fasterxml.jackson.module.kotlin.* // added for clarity 

val operationalResult: OperationalResult<Long> = mapper.readValue(""{"result":"5"}""") 

:彼は次のように一例を示しています)ジャクソンにデータタイプについて話すのに必要なことは何でも行うことができます。それはあなたのために舞台裏でジャクソンTypeReferenceを作成し、それをジャクソンに渡します。これは、関数のソースです:

inline fun <reified T: Any> ObjectMapper.readValue(content: String): T = readValue(content, object: TypeReference<T>() {}) 

あなたは簡単に同じをコーディングすることができますが、モジュールはあなたのためにこの仕事をするためにこれらのヘルパーの数が多いです。さらに、デフォルトではないコンストラクタや静的ファクトリメソッドも呼び出すことができます。また、Jackson 2.8 +では、null値とデフォルトのメソッドパラメータ(JSONでは値が見つからず、デフォルト値を使用できるようにする)を使って、よりインテリジェントな処理が可能です。モジュールがなければ、間もなく新しいエラーが見つかるでしょう。

mapper.typeFactory.constructParametricTypeの使用には、代わりにTypeReferenceを使用する必要があります。これは、上記と同じパターンに従う方がずっと簡単です。

val myTypeRef = object: TypeReference<SomeOtherClass>() {} 

このコードは、指定されたあなたのジェネリッククラスでTypeRefrenceのスーパータイプを持っている(object expression経由)クラスの匿名のインスタンスを作成します。 Javaリフレクションは、この情報を照会できます。

は一般的なタイプの情報を消去するので、SomeOtherClass::classまたはSomeOtherClass::class.javaを使用すると、それらの知識が必要な場合は避けてください。

ジャクソン・コトリンモジュールを使わずに何かを取り去っても、すぐに後で多くの苦痛に冒されます。あなたのKotlinをmangleする代わりに、このモジュールはこれらのタイプのエラーを取り除き、 "Kotlinのやり方"でより多くのことをすることができます。

+0

素敵できめ細かい答えをありがとう。私はすべての説明が大好きでした。私は、オブジェクト宣言、オブジェクト式(例えば、Javaのラムダ式の代用品を作成する、インラインmouselistenersなど)とコンパニオンオブジェクトを認識し使用しています。私はあなたが 'object:TypeReference (){}'と言うとき何が起こっているのか理解しています。それでも、私はあなたが物事を説明する方法が本当に好きだった。あなたのお時間をありがとうございました。 :-) –

関連する問題