2015-10-28 4 views

ответ

67

Создать это рядный весело:

inline fun <reified T> Gson.fromJson(json: String) = this.fromJson<T>(json, object: TypeToken<T>() {}.type) 

, а затем вы можете назвать это таким образом:

val turns = Gson().fromJson<Turns>(pref.turns) 
// or 
val turns: Turns = Gson().fromJson(pref.turns) 

ПРИМЕЧАНИЕ: Этот подход не был возможен ранее в старых версиях плагинов kotlin, но теперь вы можете его использовать.


Предыдущие Альтернативы:

АЛЬТЕРНАТИВНЫЕ 1:

val turnsType = object : TypeToken<List<Turns>>() {}.type 
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType) 

Вы должны поставить object : и конкретный тип в fromJson<List<Turns>>


ALTERNAT IVE 2:

Как @cypressious упомянуть, что может быть достигнуто также следующим образом:

inline fun <reified T> genericType() = object: TypeToken<T>() {}.type 

использование в качестве:

val turnsType = genericType<List<Turns>>() 
+3

Вы также можете создать вспомогательный метод, который делает это для вас: 'инлайн весело GenericType() = объект: TypeToken () {} .type' –

+0

или даже расширяет Gson иметь новую перегрузку fromJson, что делает это , Kotlin предназначен для расширения, поэтому продлить Gson, чтобы сделать его лучше и скрыть TypeTokens. –

+0

Я сделал предлагаемое редактирование, которое делает ответ более полным и формальным, так как этот ответ, вероятно, будет замечен многими, кто использует Gson. Я добавил объяснения в ответ и ссылки на ссылки Котлина на темы, используемые для решения проблемы ... так что людям не нужно читать все остальные ответы или комментарии, которые касаются этого. Если вы примете редактирование, я смогу удалить свой ответ ниже. –

14

Это решает проблему:

val turnsType = object : TypeToken<List<Turns>>() {}.type 
val turns = Gson().fromJson<List<Turns>>(pref.turns, turnsType) 

Первая строка создает object expression, которая сходит с TypeToken и th en получает Java Type. Затем методу Gson().fromJson нужен либо тип, указанный для результата функции (который должен соответствовать созданному TypeToken).Два варианта этой работы, как и выше, или:

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

Чтобы сделать его проще создать TypeToken вы можете создать вспомогательную функцию, которая необходима, чтобы быть inline так, что он может использовать reified type parameters:

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) 

Здесь Котлин использует определение типа с одной стороны, уступки или другой, и обновленные дженерики для встроенной функции для прохождения через полный тип (без стирания) и с использованием этого для построения TypeToken, а также сделать звонок в Gson

+0

Привет, @ Jayson, я не мог заставить его работать в этой забавной забаве в Android Studio. Кажется, все в порядке, но это не признано, когда я делаю 'Gson(). FromJson > (pref.turns)' – Juancho

+0

@juancho вы можете мне сказать, что означает «не признанный»? Ошибка компилятора? У вас есть метод расширения, импортированный и доступный сверху? –

+1

Я копирую и вставляю код в Android Studio и импортировал удовольствие в моем классе kotlin. Я попытался сделать то, что вы сказали, но по какой-то причине компилятор сказал мне, что этого удовольствия не существует. Я уже использую другие функции расширения, но я не знаю, что ваше предложение не работает. Какую версию AS и Kotlin вы используете? просто повторить попытку. – Juancho

2

Это также работает и проще

inline fun <reified T> Gson.fromJson(json: String) : T = 
     this.fromJson<T>(json, T::class.java) 
+0

Тип возврата должен иметь значение NULL. В противном случае код Java в библиотеке Gson может возвращать значение null, но Kotlin предполагает, что тип не имеет значения NULL. В результате вы получаете NPE в Котлине. – fdermishin

0

Другой вариант (не уверен, что он выглядит более элегантно, чем другие) может быть вызов, как это:

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

Таким образом, вы используете Java массив класса один лайнер вместо «чистого Котлин» ,

Смежные вопросы