[generics] Kotlin에서 Gson과 함께 TypeToken + 제네릭을 사용하는 방법

사용자 지정 클래스 (Turns)에서 제네릭 유형 목록을 가져올 수 없습니다.

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)

첫 번째 줄은 그로부터 내려온 객체 표현식 을 생성하고 그로부터 TypeTokenJava를 가져옵니다 Type. 그런 다음 Gson().fromJson메서드는 함수 결과에 대해 지정된 유형 ( TypeToken생성 된 것과 일치해야 함 )이 필요합니다. 이 작품의 두 가지 버전은 위와 같습니다.

val turns: List<Turns> = Gson().fromJson(pref.turns, turnsType)

더 쉽게 만들 수 있도록 TypeToken도움말 함수를 만들 수 있습니다.이 함수는 수정 된 유형 매개 변수를 사용할 수 있도록 인라인 이어야합니다 .

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은 할당의 한쪽 또는 다른 쪽에서 유형 추론을 사용하고 인라인 함수가 전체 유형을 통과하도록 제네릭을 수정하고 (지우기없이)이를 사용하여 a를 생성하고 TypeTokenGson을 호출합니다.


답변

다른 옵션 (다른 것보다 더 우아하게 보이는지 확실하지 않음)은 다음과 같은 호출 일 수 있습니다.

turns = Gson().fromJson(allPurchasesString, Array<Turns>::class.java).toMutableList()

따라서 “pure Kotlin”대신 Java Array 클래스 1 개 라이너를 사용하고 있습니다.


답변

val obj: MutableList<SaleItemResponse> = Gson().fromJson(messageAfterDecrypt,
    object : TypeToken<List<SaleItemResponse>>() {}.type)

kotlin에서 데이터 배열을 구문 분석하는 방법입니다.


답변

나는 변환하려면이 같은 것을 사용 Tstring& 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)


답변

generic reified functionGson의 Kotlin 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
}