Gson - конвертировать из Json в типизированный ArrayList <T>

211

Используя библиотеку Gson, как мне преобразовать строку JSON ArrayListв пользовательский класс JsonLog? По сути, JsonLogэто интерфейс, реализованный различными типами журналов, созданных моим Android-приложением - журналы SMS, журналы вызовов, журналы данных - и это ArrayListколлекция всех из них. Я продолжаю получать сообщение об ошибке в строке 6.

public static void log(File destination, JsonLog log) {
    Collection<JsonLog> logs = null;
    if (destination.exists()) {
        Gson gson = new Gson();
        BufferedReader br = new BufferedReader(new FileReader(destination));
        logs = gson.fromJson(br, ArrayList<JsonLog>.class); // line 6
        // logs.add(log);
        // serialize "logs" again
    }
}

Кажется, компилятор не понимает, что я имею в виду типизированный ArrayList. Что мне делать?

Мэтью Кирос
источник
Пожалуйста, также обратитесь к stackoverflow.com/questions/44589381/… для другого подхода
Pankaj Jaiswal

Ответы:

516

Вы можете использовать TypeToken для загрузки строки json в пользовательский объект.

logs = gson.fromJson(br, new TypeToken<List<JsonLog>>(){}.getType());

Документация:

Представляет собой обобщенный тип T .

Java пока не предоставляет способ представления универсальных типов, так что этот класс делает. Вынуждает клиентов создавать подкласс этого класса, который позволяет получать информацию о типе даже во время выполнения.

Например, чтобы создать литерал типа для List<String>, вы можете создать пустой анонимный внутренний класс:

TypeToken<List<String>> list = new TypeToken<List<String>>() {};

Этот синтаксис нельзя использовать для создания литералов типа, имеющих параметры подстановки, такие как Class<?>или List<? extends CharSequence>.

Котлин:

Если вам нужно сделать это в Kotlin, вы можете сделать это так:

val myType = object : TypeToken<List<JsonLong>>() {}.type
val logs = gson.fromJson<List<JsonLong>>(br, myType)

Или вы можете увидеть этот ответ для различных альтернатив.

Alex
источник
3
попробовал этот подход, и я получил ошибку компиляции, говоря, что TypeToken () имеет только защищенный доступ
Джонатан
1
@ Джонни У меня та же проблема. Какие-либо решения?
Запнологика
15
если вы получаете ошибку защищенного доступа, вы пропустили { }ранее.getType()
Zapnologica
@ Алекс сначала десериализует в массив, затем массив преобразуется в список или напрямую десериализуется в список?
Аднан Али
Целиком корова! Я бы подумал, что ... ну ... никогда. Спасибо.
Джон Уорд
26

Ваш образец JSON:

{
    "status": "ok",
    "comment": "",
    "result": {
    "id": 276,
    "firstName": "mohamed",
    "lastName": "hussien",
    "players": [
            "player 1",
            "player 2",
            "player 3",
            "player 4",
            "player 5"
    ]
}

так что если вы хотите сохранить массив модулей в ваших SharedPrefferences так:

1- преобразует ваш возвращенный массив для формата json, используя этот метод

public static String toJson(Object jsonObject) {
    return new Gson().toJson(jsonObject);
}

2- Сохраните его в общих настройках

PreferencesUtils.getInstance(context).setString("players", toJson((.....ArrayList you want to convert.....)));

3 - чтобы получить его в любое время, получите JsonString из общих настроек

String playersString= PreferencesUtils.getInstance(this).getString("players");

4 - преобразовать его снова в список массивов

public static Object fromJson(String jsonString, Type type) {
    return new Gson().fromJson(jsonString, type);
}

ArrayList<String> playersList= (ArrayList<String>) fromJson(playersString,
                    new TypeToken<ArrayList<String>>() {
                    }.getType());

Это решение также выполнимо, если вы хотите проанализировать ArrayList объектов. Надеюсь, это поможет вам с помощью библиотеки Gson .

Мохамед Хуссьен
источник
это правильное решение, но по сути то же самое, что и ответ трехлетней давности с большим количеством ненужной информации - я пришел сюда не для того, чтобы узнать о sharedPreferences
Xerus
8

Если вы хотите использовать массивы, это довольно просто.

logs = gson.fromJson(br, JsonLog[].class); // line 6

Предоставить JsonLogкак массивJsonLog[].class

Али Асади
источник
8

Котлин

data class Player(val name : String, val surname: String)

val json = [
  {
    "name": "name 1",
    "surname": "surname 1"
  },
  {
    "name": "name 2",
    "surname": "surname 2"
  },
  {
    "name": "name 3",
    "surname": "surname 3"
  }
]

val typeToken = object : TypeToken<List<Player>>() {}.type
val playerArray = Gson().fromJson<List<Player>>(json, typeToken)

ИЛИ

val playerArray = Gson().fromJson(json, Array<Player>::class.java)
murgupluoglu
источник
5

Почему никто не написал этот простой способ преобразования строки JSON в List ?

List<Object> list = Arrays.asList(new GsonBuilder().create().fromJson(jsonString, Object[].class));
FarukT
источник
1

Я не уверен насчет gson, но вот как вы делаете это с Jon. Образец надеюсь, что с gson должен быть похожий способ

{"Players": ["player 1", "player 2", "player 3", "player 4", "player 5"]}

===============================================

import java.io.FileReader;
import java.util.List;

import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;

public class JosnFileDemo {

    public static void main(String[] args) throws Exception
    {
        String jsonfile ="fileloaction/fileName.json";


                FileReader reader = null;
                JSONObject jsb = null;
                try {
                    reader = new FileReader(jsonfile);
                    JSONParser jsonParser = new JSONParser();
                     jsb = (JSONObject) jsonParser.parse(reader);
                } catch (Exception e) {
                    throw new Exception(e);
                } finally {
                    if (reader != null)
                        reader.close();
                }
                List<String> Players=(List<String>) jsb.get("Players");
                for (String player : Players) {
                    System.out.println(player);
                }           
    }
}
Арун Конгара
источник
@ Сагар Зала: какой пример вы ожидаете ..?
Арун Конгара
0

У вас есть такая строка .

"[{"id":2550,"cityName":"Langkawi","hotelName":"favehotel Cenang Beach - Langkawi","hotelId":"H1266070"},
{"id":2551,"cityName":"Kuala Lumpur","hotelName":"Metro Hotel Bukit Bintang","hotelId":"H835758"}]"

Затем вы можете преобразовать его в ArrayList через Gson, как

var hotels = Gson().fromJson(historyItem.hotels, Array<HotelInfo>::class.java).toList()

Вашему классу HotelInfo это должно понравиться.

import com.squareup.moshi.Json

data class HotelInfo(

    @Json(name="cityName")
    val cityName: String? = null,

    @Json(name="id")
    val id: Int? = null,

    @Json(name="hotelId")
    val hotelId: String? = null,

    @Json(name="hotelName")
    val hotelName: String? = null
)
Шихаб Уддин
источник