2011-07-22 8 views
25

Obecnie pracuję nad projektem Android, który wymaga ode mnie wywołania usługi internetowej, która zwróci mi plik json. Używam biblioteki GSON do analizowania wszystkich plików json i uzyskania obiektu JSON. Działa to dobrze, dopóki nie natknę się na te dane json, które są dynamiczne w kluczowych polach. Przykładem tego pliku jest jak poniżej:Używanie GSON do parsowania JSON-a z dynamicznym "kluczem" i "wartością" w Androidzie

{ "0": { "count":"5"}, 
    "1": { "title":"...", "desc":"" }, 
    "2": { "title":"...", "desc":"" }, 
    "3": { "title":"...", "desc":"" }, 
    "4": { "title":"...", "desc":"" }, 
    "5": { "title":"...", "desc":"" }, 
    "routes": { "route1":"...", "route3":"" }, 
} 

jestem w stanie uzyskać zliczania na podstawie klucza id „0”, ale nie jestem pewien, w jaki sposób mogę skorzystać z tej wartości, aby uzyskać drugi kluczowe obiekty (identyfikator klucza 1-5), które składają się z danych, które były mi potrzebne. Naprawdę doceniam, jeśli ktoś może mi pomóc w tej sprawie. Dzięki.

+0

Chciałbym dodać, że jeśli twoja mapa nie jest zagnieżdżona, rzeczy są znacznie prostsze http://stackoverflow.com/questions/2779251/ how-can-i-convert-json-to-a-hashmap-using-gson –

Odpowiedz

30

Najbardziej prostym podejściem, jakie mogę sobie wyobrazić, to po prostu potraktowanie struktury jako Map (z Map).

Z Gsonem jest to stosunkowo łatwe do wykonania, o ile struktura Map jest statycznie znana, każda gałąź z korzenia ma taką samą głębokość, a wszystko to jest String.

import java.io.FileReader; 
import java.lang.reflect.Type; 
import java.util.Map; 

import com.google.gson.Gson; 
import com.google.gson.reflect.TypeToken; 

public class GsonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    Gson gson = new Gson(); 
    Type mapType = new TypeToken<Map<String,Map<String, String>>>() {}.getType(); 
    Map<String,Map<String, String>> map = gson.fromJson(new FileReader("input.json"), mapType); 
    System.out.println(map); 

    // Get the count... 
    int count = Integer.parseInt(map.get("0").get("count")); 

    // Get each numbered entry... 
    for (int i = 1; i <= count; i++) 
    { 
     System.out.println("Entry " + i + ":"); 
     Map<String, String> numberedEntry = map.get(String.valueOf(i)); 
     for (String key : numberedEntry.keySet()) 
     System.out.printf("key=%s, value=%s\n", key, numberedEntry.get(key)); 
    } 

    // Get the routes... 
    Map<String, String> routes = map.get("routes"); 

    // Get each route... 
    System.out.println("Routes:"); 
    for (String key : routes.keySet()) 
     System.out.printf("key=%s, value=%s\n", key, routes.get(key)); 
    } 
} 

Do bardziej dynamicznej obsługi Map struktury, zdecydowanie sugerują przejście do korzystania Jackson zamiast Gson, jak Jackson będzie deserializować dowolny obiekt JSON dowolnej złożoności w Javie Map, z jednej prostej linii kodu, i automatycznie zachowa typy prymitywów.

import java.io.File; 
import java.util.Map; 

import org.codehaus.jackson.map.ObjectMapper; 

public class JacksonFoo 
{ 
    public static void main(String[] args) throws Exception 
    { 
    ObjectMapper mapper = new ObjectMapper(); 
    Map map = mapper.readValue(new File("input.json"), Map.class); 
    System.out.println(map); 
    } 
} 

To samo można osiągnąć za pomocą Gson, ale wymaga to kilkudziesięciu linii kodu. (Plus, Gson ma inne braki, które sprawiają, że przejście na Jacksona jest tego warte).

+0

Cześć, dziękuję za rozwiązanie! Działa idealnie. =) – Philip

+2

W Gson obecnie działa to: Map jsondata = g.fromJson (injson, Map.class); – Teddy

1

Po prostu można uzyskać pojedyncze kluczowe obiekty za pomocą licznika. Więc otrzymasz obiekt "1", a następnie otrzymasz obiekt "title" i "desc", następnie obiekt "2" itd.

+1

Rozwiązałem mój problem używając rozwiązania Bruce'a. Mimo wszystko, dziękuję za twoją pomoc. =) – Philip

Powiązane problemy