Conversione di dati JSON in oggetto Java


262

Voglio essere in grado di accedere alle proprietà da una stringa JSON nel mio metodo di azione Java. La stringa è disponibile semplicemente dicendomyJsonString = object.getJson() . Di seguito è riportato un esempio di come può apparire la stringa:

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

In questa stringa ogni oggetto JSON contiene una matrice di altri oggetti JSON. L'intenzione è quella di estrarre un elenco di ID in cui un determinato oggetto possiede una proprietà di gruppo che contiene altri oggetti JSON. Ho guardato Gson di Google come un potenziale plug-in JSON. Qualcuno può offrire una qualche forma di guida su come posso generare Java da questa stringa JSON?



Risposte:


329

Ho guardato Gson di Google come un potenziale plug-in JSON. Qualcuno può offrire una qualche forma di guida su come posso generare Java da questa stringa JSON?

Google Gson supporta generics e bean nidificati. In []JSON rappresenta un array e deve essere associato a una raccolta Java come Listo solo un semplice array Java. In {}JSON rappresenta un oggetto e deve essere mappato su una Java Mapo solo su una classe JavaBean.

Hai un oggetto JSON con diverse proprietà di cui la groupsproprietà rappresenta una matrice di oggetti nidificati dello stesso tipo. Questo può essere analizzato con Gson nel modo seguente:

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

Abbastanza semplice, no? Basta avere un JavaBean adatto e chiamareGson#fromJson() .

Guarda anche:


4
Performante? L'hai davvero misurato? Sebbene GSON abbia un set di funzionalità ragionevole, ho pensato che le prestazioni fossero una sorta di punto debole (come da [ cowtowncoder.com/blog/archives/2009/09/entry_326.html] ) Come ad esempio: ho pensato che GSON non avesse davvero bisogno di setter, e era basato su campi. Quindi il codice potrebbe essere leggermente semplificato.
StaxMan,

3
Lo uso in un'app Android. Non è la soluzione più veloce possibile, ma è abbastanza semplice da programmare per giustificare la mancanza di prestazioni per l'utente fino ad ora. Forse in una versione successiva dell'app verrà rimossa per una soluzione più rapida.
Janusz,

1
Velocità Wrt, se è abbastanza veloce, è abbastanza veloce. Ho appena commentato il riferimento alla buona prestazione prevista. Il sapiente set di funzionalità di Jackson gestisce tutti gli stessi nidificazione, stratificazione, generici, quindi non è da qui che viene la differenza di velocità. Avere getter e setter non influisce sulle prestazioni in alcun modo misurabile (per i pacchetti di cui sono a conoscenza), quindi sicuramente li possono avere lì.
StaxMan,

97
+1 per il "pacchetto com.stackoverflow.q1688099;". Per qualche motivo mi ha fatto ridere.
GargantuChet

1
public String toString () {return new Gson (). toJson (this); // Usa questo invece di scrivere ogni variabile}
Prakash,

45

Bewaaaaare di Gson! È fantastico, fantastico, ma nel momento in cui vuoi fare qualcosa di diverso dai semplici oggetti, potresti facilmente aver bisogno di iniziare a costruire i tuoi serializzatori (che non è poi così difficile).

Inoltre, se hai una matrice di oggetti e deserializzi un po 'di json in quella matrice di oggetti, i veri tipi sono PERDUTI! Gli oggetti completi non saranno nemmeno copiati! Usa XStream .. Che, se si utilizza jsondriver e si impostano le impostazioni corrette, codificheranno tipi brutti nel json reale, in modo da non perdere nulla. Un piccolo prezzo da pagare (brutto json) per una vera serializzazione.

Nota che Jackson risolve questi problemi ed è più veloce di GSON.


2
Ho scritto un fork di Gson che risolve questi problemi (ed evita tutte le annotazioni di Jackson): github.com/winterstein/flexi-gson
Daniel Winterstein,

26

Stranamente, l'unico processore JSON decente menzionato finora è stato GSON.

Ecco altre buone scelte:

  • Jackson ( Github ) - potente associazione dati (da JSON a / da POJO), streaming (ultra veloce), modello ad albero (comodo per l'accesso non tipizzato)
  • Flex-JSON - serializzazione altamente configurabile

EDIT (ago / 2013):

Un altro da considerare:

  • Genson - funzionalità simile a Jackson, mirata ad essere più facile da configurare dallo sviluppatore

15

O con Jackson:

String json = "...
ObjectMapper m = new ObjectMapper();
Set<Product> products = m.readValue(json, new TypeReference<Set<Product>>() {});

Questo darà errore non può deserializzare l'istanza di java.util.HashSet dal token
START_OBJECT

7

Se, per qualsiasi modifica, ti trovi in ​​un'applicazione che utilizza già http://restfb.com/ , puoi fare:

import com.restfb.json.JsonObject;

...

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

eccetera.


la tua soluzione è più breve e più comprensibile, perché riceve solo 3 voti? C'è qualcosa che non va?
Jeff,

4

Codice Java semplice e funzionante da convertire JSONObjectinJava 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());

    }
}

Come accedere a queste proprietà JSON in JSP?
Zoran777,

Se non vuoi usarlo nella pagina JSP, il codice è sempre lo stesso. La classe Employee.java sarà la stessa. Ma il codice scritto in LoadFromJSON.java verrà copiato nella pagina jsp con l'importazione corretta di ogni classe. Resto non c'è alcun cambiamento.
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());
}

3

Se usi qualsiasi tipo di mappe speciali con chiavi o valori anche di mappe speciali, scoprirai che non è previsto dall'implementazione di google.


2

Cosa c'è che non va nelle cose standard?

JSONObject jsonObject = new JSONObject(someJsonString);
JSONArray jsonArray = jsonObject.getJSONArray("someJsonArray");
String value = jsonArray.optJSONObject(i).getString("someJsonValue");

è terribilmente lento: github.com/fabienrenaud/java-json-benchmark recentemente sul posto di lavoro, ho raddoppiato le prestazioni (utilizzo della CPU ridotto della metà, interruzione della latenza) dei nostri server di prodotti cambiando tutte le chiamate org.json ser / deserialization usare jackson.
fabien

0

Prova Boon:

https://github.com/RichardHightower/boon

È malvagio veloce:

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

Non crederci sulla parola ... dai un'occhiata al benchmark di gatling.

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

(Fino a 4x in alcuni casi, e su 100 di test. Ha anche una modalità di overlay dell'indice che è ancora più veloce. È giovane ma ha già alcuni utenti.)

Può analizzare JSON in Mappe ed elenchi più velocemente di qualsiasi altra libreria in grado di analizzare un DOM JSON e che è senza la modalità Sovrapposizione indice. Con la modalità Overlay indice Boon, è ancora più veloce.

Ha anche una modalità lassista JSON molto veloce e una modalità parser PLIST. :) (e ha una memoria super bassa, diretta dalla modalità byte con codifica UTF-8 al volo).

Ha anche la modalità più veloce da JSON a JavaBean.

È nuovo, ma se la velocità e l'API semplice sono ciò che stai cercando, non penso che ci sia un'API più veloce o più minimalista.


puoi fornire un link per la documentazione aggiornata per l'ultima versione? Ad oggi, ho trovato 0.4, ma non riesco a trovare facilmente un collegamento o tutorial doc corrispondente per quella versione. Grazie
Bizmarck,

Ecco un tutorial github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes Boon è nel repo pubblico di Maven. È a circa 0,27.
RickHigh,

richardhightower.github.io/site/releases ha 0.4, quindi ho pensato che fosse l'ultimo. Ho provato Boon per un progetto al lavoro, ha un'annotazione equivalente a @JsonIgnore di Jackson?
Bizmarck,

boon è all'estremità inferiore delle prestazioni ser / deserializzazione: github.com/fabienrenaud/java-json-benchmark Scegli jackson o dsljson per le prestazioni. @RickHigh: non ho potuto aprire un problema sul tuo github, sono più che disposto a migliorare il mio benchmark o correggere la sua interpretazione se c'è qualcosa di sbagliato / che-mi sono perso.
fabien

0

A seconda del formato di input JSON (stringa / file), creare un jSONString. L'oggetto della classe Message di esempio corrispondente a JSON può essere ottenuto come di seguito:

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


0

Il modo più semplice è che puoi usare questo metodo softconvertvalue che è un metodo personalizzato in cui puoi convertire jsonData nella tua specifica classe 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);
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.