2012-11-20 11 views
9

Mam plik JSON, który może mieć wiele typów.Parsowanie JSON-a do Jacksona przy użyciu podejścia do strumienia/obiektu

Na przykład:

{ 
    "dog": { 
     "owner" : "John Smith", 
     "name" : "Rex", 
     "toys" : { 
      "chewtoy" : "5", 
      "bone" : "1" 
     } 
    }, 
    "person": { 
     "name" : "John Doe", 
     "address" : "23 Somewhere Lane" 
    } 
    // Further examples of dogs and people, and a few other types. 
} 

chcę analizować je pod obiektami. to znaczy. Chcę utworzyć obiekt dla psa z atrybutami właściciel/nazwa/zabawki oraz osoba z atrybutami nazwa/adres i użyć Jacksona do czytania i tworzenia obiektów z nich.

Sprawy porządkowe - muszę wiedzieć, że Rex przyszedł na przykład przed John Doe. Wolałbym robić coś podobnego do strumienia (np. Czytać i parsować Rexa do obiektu Dog, zrobić z nim coś, następnie odrzucić, a następnie przejść do John Doe). Potrzebuję więc podejścia opartego na strumieniu.

Nie mogę się dowiedzieć, jak korzystać z interfejsu API do czytania strumieniowego (aby przejść w kolejności) i interfejsu ObjectMapper (w celu tworzenia obiektów Java z JSON), aby to osiągnąć.

+1

(1) Twoje pytanie o strumień lub przetwarzanie podobne do SAX jest całkowicie poprawne. +1. Ale (2) twoje dane nie są dobrze zaprojektowane, jeśli zamawianie ma znaczenie w słowniku. Słowniki JSON są z natury nieuporządkowane. Jeśli potrzebujesz zamówienia, użyj tablicy i zakoduj informacje o typie (pies/osoba) jako atrybut. –

+0

Hmm. Źródło danych jest prawdopodobnie niezmienne (nie jest pod moją kontrolą). Kiedy mówisz, użyj tablicy i zakoduj informacje, czy chcesz zrobić to ręcznie? (Przeczytaj wszystkie tokeny i stwórz odpowiednie obiekty wywołujące odpowiednie seterów) Czy jest jakiś sposób, aby to zrobić używając Jacksona? –

+0

Mam na myśli dane JSON powinny mieć postać tablicy, jeśli zamówienie ma znaczenie, z typami zakodowanymi z każdym obiektem. Ale jeśli nie kontrolujesz danych JSON, to nieważne - będziesz musiał poradzić sobie z analizowaniem strumienia, jak sugerujesz. :) Nie mam odpowiedzi na twoje aktualne pytanie, chociaż ktoś inny na pewno to zrobi. Ale wiedz, że ktokolwiek wymyślił ten format JSON, bawi się ogniem. To bardzo delikatne, polegać na kolejności kluczy w słowniku, nie wspominając o bólu w tyłku, który stwarza dla ludzi (ty), którzy próbują sobie z tym poradzić - to jest sprzeczne z większością narzędzi. –

Odpowiedz

10

Aby to zrobić, trzeba użyć mapowania obiektów ze swojej fabryki

import org.codehaus.jackson.JsonFactory; 
import org.codehaus.jackson.JsonParser; 
import org.codehaus.jackson.JsonProcessingException; 
import org.codehaus.jackson.map.ObjectMapper; 
... 
private static ObjectMapper mapper = new ObjectMapper(); 
private static JsonFactory factory = mapper.getJsonFactory(); 

Następnie należy utworzyć parser dla wejścia.

JsonParser parser = factory.createJsonParser(in); 

Teraz można łączyć wywołań parser.nextToken() i wzywa do parser.readValueAs (klasa C). Oto przykład, w którym klasy są pobierane z mapy:

Map<String, Class<?>> classMap = new HashMap<String, Class<?>>(); 
classMap.put("dog", Dog.class); 
classMap.put("person", Person.class); 

InputStream in = null; 
JsonParser parser = null; 
List<Object> results = new ArrayList<Object>(); 
try { 
    in = this.getClass().getResourceAsStream("input.json"); 
    parser = factory.createJsonParser(in); 
    parser.nextToken();// JsonToken.START_OBJECT 
    JsonToken token = null; 
    while((token = parser.nextToken()) == JsonToken.FIELD_NAME) { 
    String name = parser.getText(); 
    parser.nextToken(); // JsonToken.START_OBJECT 
    results.add(parser.readValueAs(classMap.get(name))); 
    } 
    // ASSERT: token = JsonToken.END_OBJECT 
} 
finally { 
    IOUtils.closeQuietly(in); 
    try { 
    parser.close(); 
    } 
    catch(Exception e) {} 
} 
+0

Myślę, że teraz widzę. Kiedy próbowałem to zrobić na początku, zmagałem się, ponieważ nie wiedziałbym, jakim obiektem byłem ("pies" lub "osoba"), ale jeśli dane są sformatowane jako tablica z wartościami psa/osoby jako wartości w atrybucie "typ" byłbym w stanie to zrobić. Dziękuję wszystkim. –

+0

Dobra odpowiedź. Ale byłoby wspaniale, gdybyś mógł przepisać fragment kodu za pomocą najnowszej biblioteki Jacksona. –

Powiązane problemy