Convertendo Dados JSON em Objeto Java

262

Quero poder acessar propriedades de uma sequência JSON dentro do meu método de ação Java. A string está disponível simplesmente dizendo myJsonString = object.getJson(). Abaixo está um exemplo de como a string pode ser:

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

Nesta cadeia, todo objeto JSON contém uma matriz de outros objetos JSON. A intenção é extrair uma lista de IDs em que qualquer objeto específico possui uma propriedade de grupo que contém outros objetos JSON. Eu olhei para o Gson do Google como um potencial plugin JSON. Alguém pode oferecer alguma forma de orientação sobre como eu posso gerar Java a partir dessa string JSON?

Faiyet
fonte

Respostas:

329

Eu olhei para o Gson do Google como um potencial plugin JSON. Alguém pode oferecer alguma forma de orientação sobre como eu posso gerar Java a partir dessa string JSON?

O Google Gson suporta genéricos e beans aninhados. O []em JSON representa uma matriz e deve ser mapeado para uma coleção Java como Listou apenas uma matriz Java simples. O {}JSON representa um objeto e deve ser mapeado para uma Java Mapou apenas para alguma classe JavaBean.

Você tem um objeto JSON com várias propriedades, das quais a groupspropriedade representa uma matriz de objetos aninhados do mesmo tipo. Isso pode ser analisado com o Gson da seguinte maneira:

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

Bastante simples, não é? Basta ter um JavaBean adequado e ligar Gson#fromJson().

Veja também:

BalusC
fonte
4
Desempenho? Você realmente mediu isso? Embora o GSON tenha um conjunto razoável de recursos, achei que o desempenho era um ponto fraco (conforme [ cowtowncoder.com/blog/archives/2009/09/entry_326.html] ). Por exemplo: pensei que o GSON realmente não precisava de configuradores e foi baseado em campos. Portanto, o código pode ser simplificado um pouco.
23410 StaxMan
3
Eu o uso em um aplicativo Android. Não é a solução mais rápida possível, mas é simples o suficiente para programar para justificar a falta de desempenho do usuário até agora. Talvez em uma versão posterior do aplicativo ele seja removido para uma solução mais rápida.
Janusz
1
Velocidade de Wrt, se for rápida o suficiente, é rápida o suficiente. Acabei de comentar a referência ao bom desempenho esperado. O sábio Jackson, com conjunto de recursos, lida com todos os mesmos agrupamentos, camadas e genéricos, para que não seja daí que a diferença de velocidade vem. Ter getters e setters não afeta o desempenho de nenhuma maneira mensurável (para pacotes que eu conheço), então, definitivamente, eles podem estar lá.
23410 StaxMan
97
+1 no "pacote com.stackoverflow.q1688099;". Por alguma razão, isso me fez rir.
GargantuChet
1
public String toString () {retorna novo Gson (). toJson (this); // Use isso em vez de escrever cada variável}
Prakash
45

Cuidado com o Gson! É muito legal, muito grande, mas o segundo que você quer fazer outra coisa senão objetos simples, você poderia facilmente precisa para começar a construir seus próprios serializers (que não é que difícil).

Além disso, se você tiver uma matriz de objetos e desserializar algum json nessa matriz de objetos, os tipos verdadeiros serão PERDIDOS! Os objetos completos nem serão copiados! Use XStream .. Que, se você estiver usando o jsondriver e definir as configurações apropriadas, codificará tipos feios no json real, para que você não perca nada. Um pequeno preço a pagar (json feio) pela serialização verdadeira.

Observe que Jackson corrige esses problemas e é mais rápido que o GSON.

Jor
fonte
2
Eu escrevi um garfo de Gson que corrige esses problemas (e evita todas as anotações do Jackson): github.com/winterstein/flexi-gson
Daniel Winterstein
26

Estranhamente, o único processador JSON decente mencionado até agora foi o GSON.

Aqui estão mais boas escolhas:

  • Jackson ( Github ) - poderosa ligação de dados (JSON para / de POJOs), streaming (ultra-rápido), modelo de árvore (conveniente para acesso não-tipado)
  • Flex-JSON - serialização altamente configurável

EDIT (Ago / 2013):

Mais um a considerar:

  • Genson - funcionalidade semelhante a Jackson, destinada a ser mais fácil de configurar pelo desenvolvedor
StaxMan
fonte
15

Ou com Jackson:

String json = "...
ObjectMapper m = new ObjectMapper();
Set<Product> products = m.readValue(json, new TypeReference<Set<Product>>() {});
Gene De Lisa
fonte
Isso dará erro, não é possível desserializar a instância do java.util.HashSet fora do token
START_OBJECT
7

Se, por qualquer alteração, você estiver em um aplicativo que já use http://restfb.com/ , poderá:

import com.restfb.json.JsonObject;

...

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

etc.

cherouvim
fonte
sua solução é mais curta e mais compreensível, por que recebe apenas três votos positivos? Há algo errado?
Jeff
4

Código java fácil e funcional para converter JSONObjectparaJava 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
fonte
Como acessar essas propriedades json no JSP?
Zoran777
Se você não quiser usá-lo na página JSP, o código ainda será o mesmo. A classe Employee.java será a mesma. Mas o código escrito em LoadFromJSON.java será copiado na página jsp com a importação apropriada de todas as classes. Descanse, não há mudança alguma.
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());
}
CALOR
fonte
3

Se você usar qualquer tipo de mapa especial com chaves ou valores também de mapas especiais, descobrirá que não é contemplado pela implementação do google.

Juanma
fonte
2

O que há de errado com o material padrão?

JSONObject jsonObject = new JSONObject(someJsonString);
JSONArray jsonArray = jsonObject.getJSONArray("someJsonArray");
String value = jsonArray.optJSONObject(i).getString("someJsonValue");
Kevin
fonte
é terrivelmente lento: github.com/fabienrenaud/java-json-benchmark recentemente no trabalho, eu dupliquei o desempenho (uso da CPU cortado pela metade, latência cortado pela interrupção) de nossos servidores prod alternando todas as chamadas de ser / desserialização do org.json usar jackson.
Fabian1 de
0

Experimente o boon:

https://github.com/RichardHightower/boon

É rápido demais:

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

Não acredite na minha palavra ... confira o benchmark gatling.

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

(Até 4x são alguns casos, e fora dos 100s de teste. Ele também possui um modo de sobreposição de índice ainda mais rápido. É jovem, mas já tem alguns usuários.)

Ele pode analisar JSON em Mapas e Listas mais rapidamente do que qualquer outra lib pode analisar em um DOM JSON e isso é sem o modo Index Overlay. Com o modo Boon Index Overlay, é ainda mais rápido.

Ele também possui um modo JSON lax muito rápido e um modo de análise PLIST. :) (e tem uma memória super baixa, direta do modo de bytes com codificação UTF-8 em tempo real).

Ele também possui o JSON mais rápido para o modo JavaBean.

É novo, mas se velocidade e API simples é o que você está procurando, não acho que exista uma API mais rápida ou minimalista.

RickHigh
fonte
você pode fornecer um link para a documentação atualizada da versão mais recente? A partir de hoje, encontrei o 0.4, mas não consigo encontrar facilmente um link ou tutorial de documento correspondente para essa versão. Obrigado
Bizmarck
Aqui está um tutorial github.com/RichardHightower/boon/wiki/Boon-JSON-in-five-minutes Boon está no repositório público de especialistas. É em 0,27 ou mais.
RickHigh
richardhightower.github.io/site/releases tem 0,4, então eu pensei que era o mais recente. Estive checando Boon para um projeto no trabalho, ele tem uma anotação equivalente ao @JsonIgnore de Jackson?
Bizmarck 24/09
O boon está na extremidade inferior do desempenho de ser / desserialização: github.com/fabienrenaud/java-json-benchmark Escolha jackson ou dsljson para desempenho. @ RickHigh: Eu não consegui abrir um problema no seu github, estou mais do que disposto a melhorar meu benchmark ou corrigir sua interpretação, se houver algo errado / que eu perdi.
Fabian1 de
0

Dependendo do formato JSON de entrada (string / arquivo), crie um jSONString. O objeto da classe Message Sample correspondente a JSON pode ser obtido como abaixo:

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

Shailendra Singh
fonte
0

A maneira mais fácil é usar esse método softconvertvalue, que é um método personalizado no qual você pode converter jsonData em sua classe Dto específica.

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
fonte