ฉันไม่สามารถรับรายการประเภททั่วไปจากคลาสที่กำหนดเองได้ (เทิร์น):
val turnsType = TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson(pref.turns, turnsType)
มันกล่าวว่า:
cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
ฉันไม่สามารถรับรายการประเภททั่วไปจากคลาสที่กำหนดเองได้ (เทิร์น):
val turnsType = TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson(pref.turns, turnsType)
มันกล่าวว่า:
cannot access '<init>' it is 'public /*package*/' in 'TypeToken'
คำตอบ:
สร้างความสนุกแบบอินไลน์:
inline fun <reified T> Gson.fromJson(json: String) = fromJson<T>(json, object: TypeToken<T>() {}.type)
จากนั้นคุณสามารถเรียกมันด้วยวิธีนี้:
val turns = Gson().fromJson<Turns>(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)
ทางเลือกก่อนหน้า:
ทางเลือก 1:
val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
คุณต้องใส่object :
และประเภทเฉพาะในfromJson<List<Turns>>
ทางเลือก 2:
ดังที่ @cypressious กล่าวถึงก็สามารถทำได้ด้วยวิธีนี้:
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type
ใช้เป็น:
val turnsType = genericType<List<Turns>>()
วิธีนี้ช่วยแก้ปัญหาได้:
val turnsType = object : TypeToken<List<Turns>>() {}.type
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType)
บรรทัดแรกสร้างนิพจน์อ็อบเจ็กต์ที่ต่อจากTypeToken
นั้นรับ Java Type
จากนั้น จากนั้นGson().fromJson
เมธอดต้องการชนิดที่ระบุสำหรับผลลัพธ์ของฟังก์ชัน (ซึ่งควรตรงกับที่TypeToken
สร้างขึ้น) สองเวอร์ชันของงานนี้ตามด้านบนหรือ:
val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)
เพื่อให้ง่ายต่อการสร้างTypeToken
คุณสามารถสร้างฟังก์ชันตัวช่วยซึ่งจำเป็นต้องอยู่ในบรรทัดเพื่อให้สามารถใช้พารามิเตอร์ประเภท reified :
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type
ซึ่งสามารถใช้ได้ด้วยวิธีใดวิธีหนึ่งต่อไปนี้:
val turnsType = genericType<List<Turns>>()
// or
val turnsType: List<Turns> = genericType()
และกระบวนการทั้งหมดสามารถรวมเป็นฟังก์ชันส่วนขยายสำหรับGson
อินสแตนซ์:
inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type)
เพื่อให้คุณสามารถโทรหา Gson ได้และไม่ต้องกังวลTypeToken
เลย:
val turns = Gson().fromJson<Turns>(pref.turns)
// or
val turns: Turns = Gson().fromJson(pref.turns)
ที่นี่ Kotlin ใช้การอนุมานประเภทจากด้านหนึ่งของการมอบหมายหรืออีกด้านหนึ่งและ reified generics สำหรับฟังก์ชันอินไลน์เพื่อส่งผ่านประเภทเต็ม (โดยไม่ต้องลบ) และใช้สิ่งนั้นเพื่อสร้าง a TypeToken
และโทรไปยัง Gson
Gson().fromJson<kotlin.List<Turns>>(pref.turns)
Gson()
หรือGson
เหมือนกับว่ามันเป็นแบบคงที่? คุณต้องมีอินสแตนซ์แรก
อีกทางเลือกหนึ่ง (ไม่แน่ใจว่ามันดูหรูหรากว่าตัวอื่น) อาจเป็นการเรียกแบบนี้:
turns = Gson().fromJson(allPurchasesString, Array<Turns>::class.java).toMutableList()
ดังนั้นคุณจึงใช้ซับ java Array class one แทน "pure Kotlin"
val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
object : TypeToken<List<SaleItemResponse>>() {}.type)
เป็นวิธีของฉันในการแยกวิเคราะห์อาร์เรย์ข้อมูลใน kotlin
ผมใช้บางอย่างเช่นนี้การแปลงT
ไปstring
และString
กลับไปใช้T
Gson
ไม่ใช่สิ่งที่คุณกำลังมองหา แต่ในกรณี
กำลังประกาศนามสกุล
inline fun <reified T : Any> T.json(): String = Gson().toJson(this, T::class.java)
inline fun <reified T : Any> String.fromJson(): T = Gson().fromJson(this,T::class.java)
การใช้งาน
// Passing an object to new Fragment
companion object {
private const val ARG_SHOP = "arg-shop"
@JvmStatic
fun newInstance(shop: Shop) =
ShopInfoFragment().apply {
arguments = Bundle().apply {
putString(ARG_SHOP, shop.json())
}
}
}
// Parsing the passed argument
private lateinit var shop: Shop
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
arguments?.let {
shop = it.getString(ARG_SHOP).fromJson() ?: return
}
}
วิธีนี้ใช้งานได้ดีและง่ายกว่า
inline fun <reified T> Gson.fromJson(json: String) : T =
this.fromJson<T>(json, T::class.java)
Kotlin generic reified function
of Gson deserialize เพื่อArrayList<T>
ใช้รหัสนี้
inline fun <reified T> get( ... ): ArrayList<T>{
val str = "[{},{}]"
val type = TypeToken.getParameterized(ArrayList::class.java, T::class.java).type
val t = Gson().fromJson<ArrayList<T>>(str, type)
return t
}
inline fun <reified T> genericType() = object: TypeToken<T>() {}.type