Kotlin の Json シリアル化フレームワークがデータクラス ジェネリックスを解析できない問題を解決する

まずは結果から話しましょう

Solon フレームワークに変更した後、All in kt で問題が発生しました。つまり、JSON データ レベルが深い場合、最初のレイヤーのみをシリアル化できます。これは、テスト済みの主流の JSON フレームワークの場合です。1 日かけて調査した結果、依存しない解決策をついに見つけました。まず結果コード:

@OptIn(ExperimentalStdlibApi::class)
fun main(args: Array<String>) {
    val ret = """{"code":200,"msg":"成功","data":{"id":"out123","name":"outName","inner":{"id":"inner123","name":"innerName","innerdata":["1","2","3"]}}}"""

    // inner解析结果 snack3: false | fastJson2: false | gson: false
    val snack3 = ONode.deserialize<Ret<Out>>(ret,Ret<Out>()::class.java)
    val fastJson2 = JSON.parseObject<Ret<Out>>(ret, Ret<Out>()::class.java)
    val gson = Gson().fromJson<Ret<Out>>(ret, Ret<Out>()::class.java)

    // inner解析结果 snack3: true | fastJson2: true | gson: true
    val typeOf_T = typeOf<Ret<Out>>().javaType
    val typeOf_snack3 = ONode.deserialize<Ret<Out>>(ret,typeOf_T)
    val typeOf_fastJson2 = JSON.parseObject<Ret<Out>>(ret, typeOf_T)
    val typeOf_gson = Gson().fromJson<Ret<Out>>(ret, typeOf_T)

}

data class Ret<T>(
    var code:String?=null,
    var msg:String?=null,
    var data:T?=null
)
data class Out(
    var id:String?=null,
    var name:String?=null,
    var inner:Inner?=null
)
data class Inner(
    var id:String?=null,
    var name:String?=null,
    var innerdata:List<String>?=null
)

typeOf<T>().javaType逆シリアル化に渡される Type パラメーターを使用します。ただし、このメソッドを使用するには、呼び出し側メソッドに追加する必要があります。@OptIn(ExperimentalStdlibApi::class)

詳細について話しましょう

データ クラスは確かに便利ですが、kt の設計思想により、データ クラスは最終クラスにコンパイルされます。つまり、このデータ型は継承できません。このため、上記の問題が発生し、基本的に、匿名内部クラスを使用してジェネリックスを渡す公式の方法は使用できません。

// 取自snack3文档
List<UserModel> list = ONode.deserialize(json, (new ArrayList<UserModel>(){}).getClass());

Kt は、これと同様の匿名内部クラスを実装するobject:ために使用

val list: List<UserModel> = ONode.deserialize<List<UserModel>>(json, object : ArrayList<UserModel>() {}.javaClass)

公式の方法だとopen class結果を受け取るクラスを変更する必要があり、最上位層だけを変更しているのですが、書き方としては少し変で、結局そこには空のクラスが表示されています。したがって、一般的な結果クラスとデータ クラスの両方が必要な場合は、パス タイプdata classを使用するのが最善です。typeOf<T>().javaType

別の方法があります

Solon フレームワークが kt で直接使用できることを知らなかったため.javaType、フレームワークはデフォルトで Snack3 を使用します。したがって、TypeRefメソッドは kt の一般的な実現原理を使用してカプセル化されます。

inline fun <reified T> gType(): Type? {
    return object : TypeRef<T>() {}.type
}

トップレベル関数として宣言されている場合は、関数を呼び出すだけです。

val ret= ONode.deserialize<Ret<Out>>(ret,gType<Ret<Out>>())

このメソッドは基本的に匿名の内部クラスを使用しますが、内部クラスが宣言されている場所は、少なくともコードが呼び出しを表示する場所には表示されません。TypeRefただし、このメソッドはSnack3 によって提供され、 GSON で呼び出されるように見えるシリアル化フレームワークに依存していますTypeTokenこの方法が気に入った場合は、自分でカプセル化することもできます。

Raspberry Pi 5 は 10 月末にリリースされ、 WeChat と QQ で 60 米ドルから販売されます。 新しい UOS バージョンのリリースには 2 年かかり、価格は 15,000 米ドルでした。Chrome 拡張機能はどのようにして利益を得ることができますか? Java 開発者はJNotepad の構築に参加するよう呼びかけ Apple の中国 App Store は未使用の登録アプリケーションを許可しない Rust GUI ライブラリ egui 0.23 リリース、シンプルで強力な画像 API 「オープンソース Windows」を追加 ReactOS GUI 設定/インストールを改善 Python 3.12。 0 安定版と 3.11.6 がリリース RMS はがんと闘っている 中国上海サイバースペース管理局 46 のローカルアプリによる個人情報の収集と使用について特別検査を実施
{{名前}}
{{名前}}

おすすめ

転載: my.oschina.net/u/6931595/blog/10114868