Konvertieren von JSON-Daten in ein Java-Objekt

262

Ich möchte in meiner Java-Aktionsmethode über eine JSON-Zeichenfolge auf Eigenschaften zugreifen können. Die Zeichenfolge ist verfügbar, indem Sie einfach sagen myJsonString = object.getJson(). Unten sehen Sie ein Beispiel dafür, wie die Zeichenfolge aussehen kann:

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

In dieser Zeichenfolge enthält jedes JSON-Objekt ein Array anderer JSON-Objekte. Es ist beabsichtigt, eine Liste von IDs zu extrahieren, bei denen ein bestimmtes Objekt eine Gruppeneigenschaft besitzt, die andere JSON-Objekte enthält. Ich habe Googles Gson als potenzielles JSON-Plugin angesehen. Kann jemand eine Anleitung geben, wie ich Java aus dieser JSON-Zeichenfolge generieren kann?

Faiyet
quelle

Antworten:

329

Ich habe Googles Gson als potenzielles JSON-Plugin angesehen. Kann jemand eine Anleitung geben, wie ich Java aus dieser JSON-Zeichenfolge generieren kann?

Google Gson unterstützt Generika und verschachtelte Beans. Das []in JSON stellt ein Array dar und sollte einer Java-Sammlung wie Listoder nur einem einfachen Java-Array zugeordnet werden. Das {}in JSON stellt ein Objekt dar und sollte einer Java- Mapoder nur einer JavaBean-Klasse zugeordnet werden.

Sie haben ein JSON-Objekt mit mehreren Eigenschaften, von denen die groupsEigenschaft ein Array verschachtelter Objekte desselben Typs darstellt. Dies kann mit Gson folgendermaßen analysiert werden:

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

Ziemlich einfach, nicht wahr? Habe einfach eine passende JavaBean und rufe auf Gson#fromJson().

Siehe auch:

BalusC
quelle
4
Performant? Hast du es tatsächlich gemessen? Obwohl GSON über einen angemessenen Funktionsumfang verfügt, dachte ich, dass die Leistung eine Art Schwachstelle ist (gemäß [ cowtowncoder.com/blog/archives/2009/09/entry_326.html] ). Zum Beispiel: Ich dachte, GSON brauchte keine Setter wirklich, und basierte auf Feldern. Der Code könnte also leicht vereinfacht werden.
StaxMan
3
Ich benutze es in einer Android App. Es ist nicht die schnellstmögliche Lösung, aber es ist einfach genug zu programmieren, um den Leistungsmangel für den Benutzer bis jetzt zu rechtfertigen. Möglicherweise wird es in einer späteren Version der App für eine schnellere Lösung entfernt.
Janusz
1
Wrt Geschwindigkeit, wenn es schnell genug ist, ist es schnell genug. Ich habe gerade den Hinweis auf die erwartete gute Leistung kommentiert. In Bezug auf die Funktionen übernimmt Jackson die gleichen Verschachtelungen, Überlagerungen und Generika. Daher kommt der Geschwindigkeitsunterschied nicht daher. Getter und Setter zu haben, hat keinen messbaren Einfluss auf die Leistung (für Pakete, die mir bekannt sind), daher können sie definitiv vorhanden sein.
StaxMan
97
+1 für das "Paket com.stackoverflow.q1688099;". Aus irgendeinem Grund brachte es mich zum Lachen.
GargantuChet
1
public String toString () {neues Gson () zurückgeben. toJson (this); // Verwenden Sie dies, anstatt jede Variable zu schreiben}
Prakash
45

Bewaaaaare von Gson! Es ist sehr cool, sehr gut, aber sobald Sie etwas anderes als einfache Objekte ausführen möchten, müssen Sie möglicherweise Ihre eigenen Serializer erstellen (was nicht so schwierig ist).

Wenn Sie ein Array von Objekten haben und etwas JSON in dieses Array von Objekten deserialisieren, sind die wahren Typen VERLOREN! Die vollständigen Objekte werden nicht einmal kopiert! Verwenden Sie XStream. Wenn Sie den jsondriver verwenden und die richtigen Einstellungen vornehmen, werden hässliche Typen in den tatsächlichen json codiert, sodass Sie nichts verlieren. Ein kleiner Preis (hässlicher JSON) für echte Serialisierung.

Beachten Sie, dass Jackson diese Probleme behebt und schneller als GSON ist.

Jor
quelle
2
Ich habe eine Gabel von Gson geschrieben, die diese Probleme behebt (und alle Anmerkungen des Jackson vermeidet): github.com/winterstein/flexi-gson
Daniel Winterstein
26

Seltsamerweise war GSON der einzige anständige JSON-Prozessor, der bisher erwähnt wurde.

Hier sind weitere gute Möglichkeiten:

  • Jackson ( Github ) - Leistungsstarke Datenbindung (JSON zu / von POJOs), Streaming (ultraschnell), Baummodell (praktisch für untypisierten Zugriff)
  • Flex-JSON - hoch konfigurierbare Serialisierung

EDIT (Aug / 2013):

Noch etwas zu beachten:

  • Genson - Funktionalität ähnlich wie Jackson, die vom Entwickler einfacher zu konfigurieren sein soll
StaxMan
quelle
15

Oder mit Jackson:

String json = "...
ObjectMapper m = new ObjectMapper();
Set<Product> products = m.readValue(json, new TypeReference<Set<Product>>() {});
Gene De Lisa
quelle
Dies wird Fehler geben kann Instanz von java.util.HashSet nicht aus START_OBJECT Token deserialisieren
Dipen Chawla
7

Wenn Sie sich durch eine Änderung in einer Anwendung befinden, die bereits http://restfb.com/ verwendet , können Sie Folgendes tun:

import com.restfb.json.JsonObject;

...

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

etc.

Cherouvim
quelle
Ihre Lösung ist kürzer und verständlicher. Warum erhält sie nur 3 Upvotes? Ist irgendwas falsch?
Jeff
4

Einfach und arbeiten Java - Code konvertieren JSONObjectzuJava 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
quelle
Wie greife ich in JSP auf diese JSON-Eigenschaften zu?
Zoran777
Wenn Sie es nicht auf einer JSP-Seite verwenden möchten, ist der Code immer noch derselbe. Die Employee.java-Klasse ist dieselbe wie sie ist. Der in LoadFromJSON.java geschriebene Code wird jedoch auf der JSP-Seite mit dem richtigen Import jeder Klasse kopiert. Ruhe, es gibt überhaupt keine Veränderung.
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());
}
HITZE
quelle
3

Wenn Sie spezielle Karten mit Schlüsseln oder Werten verwenden, auch für spezielle Karten, werden Sie feststellen, dass dies bei der Implementierung von Google nicht berücksichtigt wird.

Juanma
quelle
2

Was ist los mit dem Standardmaterial?

JSONObject jsonObject = new JSONObject(someJsonString);
JSONArray jsonArray = jsonObject.getJSONArray("someJsonArray");
String value = jsonArray.optJSONObject(i).getString("someJsonValue");
Kevin
quelle
Es ist furchtbar langsam: github.com/fabienrenaud/java-json-benchmark Vor kurzem habe ich die Leistung (halbierte CPU-Auslastung, Unterbrechung der Latenz) unserer Produktserver verdoppelt, indem ich alle ser.- / deserialization-Aufrufe von org.json umgeschaltet habe Jackson benutzen.
Fabien
0

Probieren Sie es aus:

https://github.com/RichardHightower/boon

Es ist schnell böse:

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

Nehmen Sie nicht mein Wort dafür ... sehen Sie sich den Gatling-Benchmark an.

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

(In einigen Fällen bis zu 4x und in den 100 Testjahren. Es gibt auch einen Index-Overlay-Modus, der noch schneller ist. Er ist jung, hat aber bereits einige Benutzer.)

Es kann JSON schneller in Karten und Listen analysieren als jede andere Bibliothek, die in ein JSON-DOM analysiert werden kann, und das ohne Index-Overlay-Modus. Mit dem Boon Index Overlay-Modus ist es sogar noch schneller.

Es hat auch einen sehr schnellen JSON-Lax-Modus und einen PLIST-Parser-Modus. :) (und hat einen super niedrigen Speicher, direkt aus dem Byte-Modus mit UTF-8-Codierung im laufenden Betrieb).

Es hat auch den schnellsten JSON-zu-JavaBean-Modus.

Es ist neu, aber wenn Sie nach Geschwindigkeit und einfacher API suchen, gibt es meiner Meinung nach keine schnellere oder minimalistischere API.

RickHigh
quelle
Können Sie einen Link für die aktuelle Dokumentation der neuesten Version bereitstellen? Bis heute habe ich 0.4 gefunden, kann aber keinen passenden Dokumentlink oder Tutorial für diese Version finden. Danke
Bizmarck
Hier ist ein Tutorial github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes Boon ist im öffentlichen Maven Repo. Es ist bei 0,27 oder so.
RickHigh
richardhightower.github.io/site/releases hat 0.4, also dachte ich, das war das Neueste. Ich habe Boon nach einem Projekt bei der Arbeit durchsucht. Hat es eine entsprechende Anmerkung zu Jacksons @JsonIgnore?
Bizmarck
Segen ist am unteren Ende der Ser / Deserialization-Leistung: github.com/fabienrenaud/java-json-benchmark Wählen Sie Jackson oder Dsljson für die Leistung. @ RickHigh: Ich konnte kein Problem mit Ihrem Github eröffnen. Ich bin mehr als bereit, meinen Benchmark zu verbessern oder seine Interpretation zu korrigieren, wenn etwas falsch ist / das ich verpasst habe.
Fabien
0

Erstellen Sie abhängig vom eingegebenen JSON-Format (Zeichenfolge / Datei) einen jSONString. Ein Beispiel für ein Nachrichtenklassenobjekt, das JSON entspricht, kann wie folgt abgerufen werden:

Nachricht msgFromJSON = neuer ObjectMapper (). ReadValue (jSONString, Message.class);

Shailendra Singh
quelle
0

Am einfachsten ist es, wenn Sie diese softconvertvalue-Methode verwenden, eine benutzerdefinierte Methode, mit der Sie jsonData in Ihre spezifische Dto-Klasse konvertieren können.

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
quelle