Conversion de données JSON en objet Java

262

Je veux pouvoir accéder aux propriétés d'une chaîne JSON dans ma méthode d'action Java. La chaîne est disponible en disant simplement myJsonString = object.getJson(). Voici un exemple de ce à quoi la chaîne peut ressembler:

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

Dans cette chaîne, chaque objet JSON contient un tableau d'autres objets JSON. L'intention est d'extraire une liste d'ID où tout objet donné possédant une propriété de groupe qui contient d'autres objets JSON. J'ai regardé Gson de Google comme un plugin JSON potentiel. Quelqu'un peut-il offrir une certaine forme de conseils sur la façon dont je peux générer Java à partir de cette chaîne JSON?

Faiyet
la source

Réponses:

329

J'ai regardé Gson de Google comme un plugin JSON potentiel. Quelqu'un peut-il offrir une certaine forme de conseils sur la façon dont je peux générer Java à partir de cette chaîne JSON?

Google Gson prend en charge les génériques et les beans imbriqués. Dans []JSON représente un tableau et doit correspondre à une collection Java telle que Listou simplement un tableau Java ordinaire. Le {}JSON dans représente un objet et doit correspondre à un Java Mapou simplement une classe JavaBean.

Vous avez un objet JSON avec plusieurs propriétés dont la groupspropriété représente un tableau d'objets imbriqués du même type. Cela peut être analysé avec Gson de la manière suivante:

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

Assez simple, non? Ayez juste un JavaBean approprié et appelez Gson#fromJson().

Voir également:

BalusC
la source
4
Performant? L'avez-vous réellement mesuré? Bien que GSON ait un ensemble de fonctionnalités raisonnable, je pensais que les performances étaient en quelque sorte un point faible (selon [ cowtowncoder.com/blog/archives/2009/09/entry_326.html] ) Quant à l'exemple: je pensais que GSON n'avait pas vraiment besoin de setters était basé sur les champs. Le code pourrait donc être légèrement simplifié.
StaxMan
3
Je l'utilise dans une application Android. Ce n'est pas la solution la plus rapide possible mais elle est assez simple à programmer pour justifier jusqu'à présent le manque de performances de l'utilisateur. Peut-être que dans une version ultérieure de l'application, elle sera supprimée pour une solution plus rapide.
Janusz
1
Par rapport à la vitesse, si c'est assez rapide, c'est assez rapide. Je viens de commenter la référence aux bonnes performances attendues. En ce qui concerne les fonctionnalités, Jackson gère tous les mêmes imbrication, superposition, génériques, donc ce n'est pas de là que vient la différence de vitesse. Avoir des getters et des setters n'affecte pas les performances de manière mesurable (pour les packages que je connais), donc peut certainement les avoir là.
StaxMan
97
+1 pour le "package com.stackoverflow.q1688099;". Pour une raison quelconque, cela m'a fait rire.
GargantuChet
1
public String toString () {return new Gson (). toJson (this); // Utilisez ceci au lieu d'écrire chaque variable}
Prakash
45

Bewaaaaare of Gson! C'est très cool, très bien, mais la seconde où vous voulez faire autre chose que de simples objets, vous pourriez facilement avoir besoin de commencer à construire vos propres sérialiseurs (ce qui n'est pas si difficile).

De plus, si vous avez un tableau d'objets et que vous désérialisez du json dans ce tableau d'objets, les vrais types sont PERDUS! Les objets complets ne seront même pas copiés! Utilisez XStream .. Qui, si vous utilisez le jsondriver et définissez les paramètres appropriés, encodera les types laids dans le json réel, afin que vous ne perdiez rien. Un petit prix à payer (moche json) pour une véritable sérialisation.

Notez que Jackson résout ces problèmes et est plus rapide que GSON.

Jor
la source
2
J'ai écrit un fork de Gson qui corrige ces problèmes (et évite toutes les annotations de Jackson): github.com/winterstein/flexi-gson
Daniel Winterstein
26

Curieusement, le seul processeur JSON décent mentionné jusqu'à présent a été GSON.

Voici d'autres bons choix:

  • Jackson ( Github ) - liaison de données puissante (JSON vers / depuis POJO), streaming (ultra rapide), modèle d'arbre (pratique pour un accès non typé)
  • Flex-JSON - sérialisation hautement configurable

EDIT (août / 2013):

Un de plus à considérer:

  • Genson - fonctionnalité similaire à Jackson, destinée à être plus facile à configurer par le développeur
StaxMan
la source
15

Ou avec Jackson:

String json = "...
ObjectMapper m = new ObjectMapper();
Set<Product> products = m.readValue(json, new TypeReference<Set<Product>>() {});
Gene De Lisa
la source
Cela donnera une erreur ne peut pas désérialiser l'instance de java.util.HashSet à partir du jeton
START_OBJECT
7

Si, par quelque changement que ce soit, vous êtes dans une application qui utilise déjà http://restfb.com/, vous pouvez faire:

import com.restfb.json.JsonObject;

...

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

etc.

cherouvim
la source
votre solution est plus courte et plus compréhensible, pourquoi ne reçoit-elle que 3 votes positifs? Y a-t-il quelque chose qui ne va pas?
Jeff
4

Code java simple et fonctionnel pour convertir JSONObjectenJava 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
la source
Comment accéder à ces propriétés json dans JSP?
Zoran777
Si vous ne voulez pas l'utiliser dans la page JSP, le code est toujours le même. La classe Employee.java sera la même qu'elle est. Mais le code écrit dans LoadFromJSON.java sera copié dans la page jsp avec l'importation appropriée de chaque classe. Reste qu'il n'y a aucun changement.
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());
}
CHALEUR
la source
3

Si vous utilisez n'importe quel type de cartes spéciales avec des clés ou des valeurs également des cartes spéciales, vous constaterez que cela n'est pas envisagé par la mise en œuvre de Google.

Juanma
la source
2

Quel est le problème avec les trucs standard?

JSONObject jsonObject = new JSONObject(someJsonString);
JSONArray jsonArray = jsonObject.getJSONArray("someJsonArray");
String value = jsonArray.optJSONObject(i).getString("someJsonValue");
Kevin
la source
c'est terriblement lent: github.com/fabienrenaud/java-json-benchmark récemment au travail, j'ai doublé les performances (utilisation du processeur réduite de moitié, latence réduite à l'arrêt) de nos serveurs de production en basculant tous les appels org.json ser / deserialization d'utiliser jackson.
fabien
0

Essayez Boon:

https://github.com/RichardHightower/boon

Il est méchant vite:

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

Ne me croyez pas sur parole ... jetez un œil à la référence Gatling.

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

(Jusqu'à 4x, dans certains cas, et sur les 100s de test. Il dispose également d'un mode de superposition d'index encore plus rapide. Il est jeune mais a déjà quelques utilisateurs.)

Il peut analyser JSON vers des cartes et des listes plus rapidement que n'importe quelle autre bibliothèque ne peut analyser vers un DOM JSON et sans le mode de superposition d'index. Avec le mode Boon Index Overlay, c'est encore plus rapide.

Il dispose également d'un mode lax JSON très rapide et d'un mode analyseur PLIST. :) (et a une mémoire super faible, directement à partir du mode octets avec encodage UTF-8 à la volée).

Il dispose également du mode JSON vers JavaBean le plus rapide.

C'est nouveau, mais si la vitesse et l'API simple sont ce que vous recherchez, je ne pense pas qu'il existe une API plus rapide ou plus minimaliste.

RickHigh
la source
pouvez-vous fournir un lien vers une documentation à jour pour la dernière version? À ce jour, j'ai trouvé 0.4, mais je ne trouve pas facilement un lien de doc ou un tutoriel correspondant pour cette version. Merci
Bizmarck
Voici un tutoriel github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes Boon est dans le repo public maven. Il est à environ 0,27.
RickHigh
richardhightower.github.io/site/releases a 0.4, donc je pensais que c'était la dernière. J'ai vérifié Boon pour un projet au travail, a-t-il une annotation équivalente à @JsonIgnore de Jackson?
Bizmarck
boon est à l'extrémité inférieure des performances de ser / désérialisation: github.com/fabienrenaud/java-json-benchmark Choisissez jackson ou dsljson pour les performances. @RickHigh: Je n'ai pas pu ouvrir un problème sur votre github, je suis plus que disposé à améliorer mon indice de référence ou à corriger son interprétation s'il y a quelque chose de mal / que cela m'a manqué.
fabien
0

Selon le format JSON d'entrée (chaîne / fichier), créez une jSONString. Un exemple d'objet de classe Message correspondant à JSON peut être obtenu comme ci-dessous:

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

Shailendra Singh
la source
0

La manière la plus simple est d'utiliser cette méthode de conversion de valeur douce qui est une méthode personnalisée dans laquelle vous pouvez convertir jsonData en votre classe Dto spécifique.

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
la source