Konwertowanie danych JSON na obiekt Java

262

Chcę mieć dostęp do właściwości z ciągu JSON w ramach mojej metody działania Java. Ciąg jest dostępny po prostu mówiąc myJsonString = object.getJson(). Poniżej znajduje się przykład tego, jak może wyglądać ciąg:

{
    'title': 'ComputingandInformationsystems',
    'id': 1,
    'children': 'true',
    'groups': [{
        'title': 'LeveloneCIS',
        'id': 2,
        'children': 'true',
        'groups': [{
            'title': 'IntroToComputingandInternet',
            'id': 3,
            'children': 'false',
            'groups': []
        }]
    }]
}

W tym ciągu każdy obiekt JSON zawiera tablicę innych obiektów JSON. Celem jest wyodrębnienie listy identyfikatorów, w których dowolny obiekt posiadający właściwość grupy, która zawiera inne obiekty JSON. Patrzyłem na Google'a Gson jako potencjalną wtyczkę JSON. Czy ktoś może zaoferować jakieś wskazówki, jak wygenerować Javę na podstawie tego ciągu JSON?

Fajjet
źródło

Odpowiedzi:

329

Patrzyłem na Google'a Gson jako potencjalną wtyczkę JSON. Czy ktoś może zaoferować jakieś wskazówki, jak wygenerować Javę na podstawie tego ciągu JSON?

Google Gson obsługuje generyczne i zagnieżdżone ziarna. []W JSON reprezentuje tablicę i należy do zbioru map, takich jak Java Listczy tylko zwykły tablica Java. {}W JSON reprezentuje obiekt i należy mapować do Javy Map, czy tylko niektóre klasy JavaBeans.

Masz obiekt JSON z kilkoma właściwościami, których groupswłaściwość reprezentuje tablicę zagnieżdżonych obiektów tego samego typu. Można to przeanalizować za pomocą Gson w następujący sposób:

package com.stackoverflow.q1688099;

import java.util.List;
import com.google.gson.Gson;

public class Test {

    public static void main(String... args) throws Exception {
        String json = 
            "{"
                + "'title': 'Computing and Information systems',"
                + "'id' : 1,"
                + "'children' : 'true',"
                + "'groups' : [{"
                    + "'title' : 'Level one CIS',"
                    + "'id' : 2,"
                    + "'children' : 'true',"
                    + "'groups' : [{"
                        + "'title' : 'Intro To Computing and Internet',"
                        + "'id' : 3,"
                        + "'children': 'false',"
                        + "'groups':[]"
                    + "}]" 
                + "}]"
            + "}";

        // Now do the magic.
        Data data = new Gson().fromJson(json, Data.class);

        // Show it.
        System.out.println(data);
    }

}

class Data {
    private String title;
    private Long id;
    private Boolean children;
    private List<Data> groups;

    public String getTitle() { return title; }
    public Long getId() { return id; }
    public Boolean getChildren() { return children; }
    public List<Data> getGroups() { return groups; }

    public void setTitle(String title) { this.title = title; }
    public void setId(Long id) { this.id = id; }
    public void setChildren(Boolean children) { this.children = children; }
    public void setGroups(List<Data> groups) { this.groups = groups; }
    
    public String toString() {
        return String.format("title:%s,id:%d,children:%s,groups:%s", title, id, children, groups);
    }
}

Dość proste, prawda? Wystarczy mieć odpowiedni JavaBean i zadzwonić Gson#fromJson().

Zobacz też:

BalusC
źródło
4
Performant? Czy rzeczywiście to zmierzyłeś? Chociaż GSON ma rozsądny zestaw funkcji, myślałem, że wydajność jest słabym punktem (zgodnie z [ cowtowncoder.com/blog/archives/2009/09/entry_326.html] ) Na przykład: Myślałem, że GSON tak naprawdę nie potrzebuje seterów, i był oparty na polach. Tak więc kod można nieco uprościć.
StaxMan,
3
Używam go w aplikacji na Androida. Nie jest to najszybsze możliwe rozwiązanie, ale wystarczy zaprogramować, aby uzasadnić brak wydajności dla użytkownika do tej pory. Być może w późniejszej wersji aplikacji zostanie ona usunięta, aby uzyskać szybsze rozwiązanie.
Janusz
1
Prędkość Wrt, jeśli jest wystarczająco szybka, jest wystarczająco szybka. Właśnie skomentowałem odniesienie do oczekiwanej dobrej wydajności. Mądry zestaw funkcji Jackson obsługuje te same zagnieżdżanie, układanie warstw, generyczne, więc nie stąd bierze się różnica prędkości. Posiadanie programów pobierających i ustawiających nie wpływa w żaden sposób na wydajność (w przypadku pakietów, o których wiem), więc na pewno mogą je tam mieć.
StaxMan
97
+1 za „pakiet com.stackoverflow.q1688099;”. Z jakiegoś powodu zachichotałem.
GargantuChet,
1
public String toString () {return new Gson (). toJson (this); // Użyj tego zamiast pisać każdą zmienną}
Prakash
45

Bewaaaaare z Gson! To bardzo fajne, bardzo świetne, ale gdy tylko chcesz zrobić coś innego niż proste przedmioty, możesz łatwo zacząć budować własne serializatory (co nie jest takie trudne).

Ponadto, jeśli masz tablicę obiektów i deserializujesz trochę jsonów w tej tablicy obiektów, prawdziwe typy są PRZEGUBIONE! Pełne obiekty nawet nie zostaną skopiowane! Użyj XStream .. Które, jeśli użyjesz jsondriver i ustawisz odpowiednie ustawienia, koduje brzydkie typy w rzeczywistym jsonie, abyś nic nie stracił. Niewielka cena do zapłacenia (brzydki Json) za prawdziwą serializację.

Pamiętaj, że Jackson rozwiązuje te problemy i jest szybszy niż GSON.

Jor
źródło
2
Napisałem rozwidlenie Gsona, które naprawia te problemy (i unika wszystkich adnotacji o Jacksonie): github.com/winterstein/flexi-gson
Daniel Winterstein
26

Co dziwne, jedynym do tej pory przyzwoitym procesorem JSON był GSON.

Oto więcej dobrych wyborów:

  • Jackson ( Github ) - potężne wiązanie danych (JSON do / z POJO), streaming (ultra szybki), model drzewa (wygodny dla dostępu bez typu)
  • Flex-JSON - wysoce konfigurowalna serializacja

EDYCJA (sierpień 2013):

Jeszcze jedna rzecz do rozważenia:

  • Genson - funkcjonalność podobna do Jacksona, której celem jest ułatwienie konfiguracji przez programistę
StaxMan
źródło
15

Lub z Jacksonem:

String json = "...
ObjectMapper m = new ObjectMapper();
Set<Product> products = m.readValue(json, new TypeReference<Set<Product>>() {});
Gene De Lisa
źródło
To da błąd, nie można deserializować wystąpienia java.util.HashSet poza token
START_OBJECT
7

Jeśli w wyniku jakiejkolwiek zmiany jesteś w aplikacji, która już korzysta z http://restfb.com/ , możesz:

import com.restfb.json.JsonObject;

...

JsonObject json = new JsonObject(jsonString);
json.get("title");

itp.

Cherouvim
źródło
Twoje rozwiązanie jest krótsze i bardziej zrozumiałe, dlaczego otrzymuje tylko 3 głosy poparcia? Czy coś jest nie tak?
Jeff
4

Proste i działa kod Java do konwersji JSONObjectdoJava Object

Employee.java

import java.util.HashMap;
import java.util.Map;

import javax.annotation.Generated;

import com.fasterxml.jackson.annotation.JsonAnyGetter;
import com.fasterxml.jackson.annotation.JsonAnySetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.annotation.JsonPropertyOrder;

@JsonInclude(JsonInclude.Include.NON_NULL)
@Generated("org.jsonschema2pojo")
@JsonPropertyOrder({
"id",
"firstName",
"lastName"
})
public class Employee {

@JsonProperty("id")
private Integer id;
@JsonProperty("firstName")
private String firstName;
@JsonProperty("lastName")
private String lastName;
@JsonIgnore
private Map<String, Object> additionalProperties = new HashMap<String, Object>();

/**
*
* @return
* The id
*/
@JsonProperty("id")
public Integer getId() {
return id;
}

/**
*
* @param id
* The id
*/
@JsonProperty("id")
public void setId(Integer id) {
this.id = id;
}

/**
*
* @return
* The firstName
*/
@JsonProperty("firstName")
public String getFirstName() {
return firstName;
}

/**
*
* @param firstName
* The firstName
*/
@JsonProperty("firstName")
public void setFirstName(String firstName) {
this.firstName = firstName;
}

/**
*
* @return
* The lastName
*/
@JsonProperty("lastName")
public String getLastName() {
return lastName;
}

/**
*
* @param lastName
* The lastName
*/
@JsonProperty("lastName")
public void setLastName(String lastName) {
this.lastName = lastName;
}

@JsonAnyGetter
public Map<String, Object> getAdditionalProperties() {
return this.additionalProperties;
}

@JsonAnySetter
public void setAdditionalProperty(String name, Object value) {
this.additionalProperties.put(name, value);
}

}

LoadFromJSON.java

import org.codehaus.jettison.json.JSONObject;

import com.fasterxml.jackson.databind.ObjectMapper;

public class LoadFromJSON {

    public static void main(String args[]) throws Exception {
        JSONObject json = new JSONObject();
        json.put("id", 2);
        json.put("firstName", "hello");
        json.put("lastName", "world");

        byte[] jsonData = json.toString().getBytes();

        ObjectMapper mapper = new ObjectMapper();
        Employee employee = mapper.readValue(jsonData, Employee.class);

        System.out.print(employee.getLastName());

    }
}
Rahul Raina
źródło
Jak uzyskać dostęp do tych właściwości json w JSP?
Zoran777
Jeśli nie chcesz go używać na stronie JSP, kod jest nadal taki sam. Klasa Employee.java będzie taka sama jak jest. Ale kod napisany w LoadFromJSON.java zostanie skopiowany na stronę jsp z odpowiednim importem każdej klasy. Reszta nie ma żadnej zmiany.
Rahul Raina
4
HashMap keyArrayList = new HashMap();
Iterator itr = yourJson.keys();
while (itr.hasNext())
{
    String key = (String) itr.next();
    keyArrayList.put(key, yourJson.get(key).toString());
}
CIEPŁO
źródło
3

Jeśli użyjesz dowolnego rodzaju specjalnych map z kluczami lub wartościami również specjalnych map, przekonasz się, że wdrożenie google nie będzie brane pod uwagę.

Juanma
źródło
2

Co jest nie tak ze standardowymi rzeczami?

JSONObject jsonObject = new JSONObject(someJsonString);
JSONArray jsonArray = jsonObject.getJSONArray("someJsonArray");
String value = jsonArray.optJSONObject(i).getString("someJsonValue");
Kevin
źródło
jest strasznie powolny: github.com/fabienrenaud/java-json-benchmark ostatnio w pracy, podwoiłem wydajność (obniżenie zużycia procesora o połowę, zmniejszenie opóźnień) naszych serwerów prod poprzez przełączenie wszystkich wywołań ser / desektualizacji org.json używać Jacksona.
fabien
0

Wypróbuj boon:

https://github.com/RichardHightower/boon

Szybko jest zły:

https://github.com/RichardHightower/json-parsers-benchmark

Nie wierz mi na słowo ... sprawdź test gatling.

https://github.com/gatling/json-parsers-benchmark

(W niektórych przypadkach maksymalnie 4x, a poza setnymi testami. Ma również tryb nakładki indeksu, który jest jeszcze szybszy. Jest młody, ale ma już niektórych użytkowników.)

Może parsować JSON do map i list szybciej niż jakakolwiek inna biblioteka może parsować do JSON DOM i to bez trybu nakładki indeksu. W trybie nakładki indeksu Boon jest jeszcze szybszy.

Ma również bardzo szybki tryb LS JSON i tryb analizatora składni PLIST. :) (i ma bardzo małą pamięć, bezpośrednio z trybu bajtów z kodowaniem UTF-8 w locie).

Ma także najszybszy tryb JSON do JavaBean.

Jest nowy, ale jeśli szukasz szybkiego i prostego interfejsu API, nie sądzę, aby istniał szybszy lub bardziej minimalistyczny interfejs API.

RickHigh
źródło
czy możesz podać link do aktualnej dokumentacji dla najnowszej wersji? Na dzień dzisiejszy znalazłem 0,4, ale nie mogę łatwo znaleźć pasującego linku do dokumentu lub samouczka dla tej wersji. Dzięki
Bizmarck,
Oto samouczek github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes Boon jest w publicznym repozytorium maven. Jest około 0,27.
RickHigh
richardhightower.github.io/site/releases ma 0.4, więc pomyślałem, że to najnowsza wersja . Sprawdzałem Boon pod kątem projektu w pracy, czy ma adnotację odpowiadającą @JsonIgnore Jacksona?
Bizmarck
boon znajduje się na dolnym końcu wydajności ser / deserializacji: github.com/fabienrenaud/java-json-benchmark Wybierz jackson lub dsljson dla wydajności. @RickHigh: Nie mogłem otworzyć problemu na twoim githubie, jestem bardziej niż chętny do ulepszenia mojego testu porównawczego lub poprawienia jego interpretacji, jeśli jest coś nie tak / źle-przeoczyłem.
fabien
0

W zależności od wejściowego formatu JSON (ciąg / plik) utwórz ciąg jSONS. Przykładowy obiekt klasy Message odpowiadający JSON można uzyskać w następujący sposób:

Komunikat msgFromJSON = new ObjectMapper (). ReadValue (jSONString, Message.class);

Shailendra Singh
źródło
0

Najprostszym sposobem jest użycie tej metody softconvertvalue, która jest niestandardową metodą, w której można przekonwertować jsonData na określoną klasę Dto.

Dto response = softConvertValue(jsonData, Dto.class);


public static <T> T softConvertValue(Object fromValue, Class<T> toValueType) 
{
    ObjectMapper objMapper = new ObjectMapper();
    return objMapper
        .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
        .convertValue(fromValue, toValueType);
}
Dipen Chawla
źródło