Gson - konwersja z Jsona na typ ArrayList <T>

211

Jak przekonwertować ciąg JSON przy użyciu biblioteki Gson ArrayListna niestandardową klasę JsonLog? Zasadniczo JsonLogjest to interfejs realizowany przez różne rodzaje dzienników tworzonych przez moją aplikację na Androida - dzienniki SMS, dzienniki połączeń, dzienniki danych - i ArrayListjest to zbiór wszystkich z nich. Wciąż pojawia się błąd w wierszu 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
    }
}

Wydaje się, że kompilator nie rozumie, że mam na myśli maszynę do pisania ArrayList. Co ja robię?

Matthew Quiros
źródło
Zobacz także inne podejście do stackoverflow.com/questions/44589381/ ...
Pankaj Jaiswal,

Odpowiedzi:

515

Możesz użyć TypeToken, aby załadować ciąg json do obiektu niestandardowego.

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

Dokumentacja:

Reprezentuje typ rodzajowy T .

Java nie zapewnia jeszcze sposobu reprezentowania typów ogólnych, więc ta klasa tak. Zmusza klientów do utworzenia podklasy tej klasy, która umożliwia pobieranie informacji o typie nawet w czasie wykonywania.

Na przykład, aby utworzyć literał typu List<String>, możesz utworzyć pustą anonimową klasę wewnętrzną:

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

Ta składnia nie może być używana do tworzenia literałów typu, które mają parametry symboli wieloznacznych, takie jak Class<?>lub List<? extends CharSequence>.

Kotlin:

Jeśli chcesz to zrobić w Kotlinie , możesz to zrobić w następujący sposób:

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

Lub możesz zobaczyć tę odpowiedź dla różnych alternatyw.

Alex
źródło
3
wypróbowałem to podejście i otrzymałem błąd kompilacji informujący, że TypeToken () ma tylko chroniony dostęp
Jonathan
1
@jonney Mam ten sam problem. Jakieś rozwiązania?
Zapnologica
15
jeśli otrzymujesz chroniony błąd dostępu, { }.getType()
pominąłeś
@Alex czy deserializuje najpierw najpierw tablicę, a następnie tablica jest konwertowana na Listę, czy bezpośrednio deserializuje na Listę?
Adnan Ali,
W pełni krowa! Uznałbym, że to ... no cóż ... nigdy. Dziękuję Ci.
John Ward
26

Twoja próbka JSON to:

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

więc jeśli chcesz zapisać listę arraylist modułów w SharedPrefrences, to:

1- przekonwertuje zwróconą tablicę do formatu json przy użyciu tej metody

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

2- Zapisz go we wspólnych preferencjach

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

3 - aby go odzyskać w dowolnym momencie pobierz JsonString z Preferencji współdzielonych w ten sposób

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

4- przekonwertować go ponownie na listę tablic

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());

to rozwiązanie jest również wykonalne, jeśli chcesz przeanalizować ArrayList of Objects. Mam nadzieję, że pomoże ci to, używając biblioteki Gson .

Mohamed Hussien
źródło
jest to prawidłowe rozwiązanie, ale w zasadzie takie samo jak trzyletnia starsza odpowiedź z dużą ilością niepotrzebnych informacji - nie przyszedłem tutaj, aby dowiedzieć się o sharedPreferences
Xerus
8

Jeśli chcesz korzystać z tablic, jest to dość proste.

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

Podaj JsonLogjako tablicęJsonLog[].class

Ali Asadi
źródło
8

Kotlin

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)

LUB

val playerArray = Gson().fromJson(json, Array<Player>::class.java)
murgupluoglu
źródło
5

Dlaczego nikt nie napisał tego prostego sposobu konwersji ciągu JSON na List ?

List<Object> list = Arrays.asList(new GsonBuilder().create().fromJson(jsonString, Object[].class));
FarukT
źródło
1

Nie jestem pewien co do gson, ale tak to robisz z Jonem. Mam nadzieję, że musi być podobny sposób korzystania z gson

{„Gracze”: [„gracz 1”, „gracz 2”, „gracz 3”, „gracz 4”, „gracz 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);
                }           
    }
}
Arun Kongara
źródło
@ Sagar Zala: jakiego przykładu oczekujesz ..?
arun kongara,
0

Masz taki ciąg .

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

Następnie możesz ukryć to w ArrayList za pośrednictwem Gson like

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

Twoja klasa HotelInfo powinna to polubić.

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
)
Shihab Uddin
źródło