O GSON é uma biblioteca Java usada para implementar a conversão mútua entre os objetos JSON e Java. O GSON é um projeto de código aberto hospedado em https://github.com/google/gson.
A classe principal em GSON é GSON. Você também pode usar a classe GsonBuilder para definir algumas opções enquanto cria objetos GSON.
Os objetos GSON não salvam nenhum estado ao processar o JSON, para que os usuários possam executar facilmente múltiplas serializações, desserialização e outras operações no mesmo objeto GSON.
Exemplo: uso básico
// Serializationgson gson = new GSON (); GSON.TOJSON (1); // ==> imprime 1gson.tojson ("ABCD"); // ==> Imprime "ABCD" GSON.TOJSON (NOVO LONG (10)); // ==> imprime 10int [] valores = {1}; gson.tojson (valores); // ==> Imprime [1] // Deserializando One = gson.fromjson ("1", int.class); número inteiro = gson.fromjson ("1", inteiro.class); long One = gson.fromjson ("1", integger.class); long = gson.fromjnson ("1", integger.class); long = gson.fromjnson ("1", integro. gson.fromjson ("false", boolean.class); string str = gson.fromjson ("/" abc/"", string.class); string anotherstr = gson.fromjson ("[/" abc/"]", string.class); //) gsonbson (gson bson bson (/"ABC/"] ", string.class); //) gsonbson (gson bson bson (/" ABC/"]", string.class); //) gsonbson (gson gson bson ("new) gson (/" new = new) gson (string) gson (string) gson ("string) gson (" gent) gson (string) gson (string) gson ("string) gson (string) gson. GSON.TOJSON (OBJ); // ==> json é {"value1": 1, "value2": "abc"}Exemplo: conversão entre um objeto e um json
Defina a aula de Pacof -Primitives:
classe BAGOF -Primitives {private int Value1 = 1; Private String Value2 = "ABC"; Transiente privado int Value3 = 3; BagofPrimitives () {// no-args construtor}}Serializado para JSON:
// serializationbagof -imitives obj = new BagofPrimitives (); gson gson = new GSON (); String json = gson.tojson (obj); // ==> json é {"value1": 1, "value2": "abc"}Não serialize objetos contendo referências circulares, caso contrário, ocorrerá uma recursão infinita.
Deserialização:
// DeserializationBagofPrimitives obj2 = gson.Fromjson (JSON, BAGOFPrimitives.class); // ==> obj2 é como obj
Alguns detalhes ao processar objetos:
Manuseio de classes aninhadas (incluindo classes internas)
O GSON pode facilmente serializar as classes aninhadas e desserializar classes aninhadas estáticas. O GSON não pode desserralizar automaticamente classes internas puras porque o construtor sem parâmea da classe interna precisa se referir ao objeto que o contém (isto é, instâncias da classe externa). Para desserializar uma classe estática, você pode estaticamente a classe interna ou fornecer um criador de instância personalizado. Aqui está um exemplo:
public classe A {public string a; classe b {public string b; public b () {// no Args construtor para b}}}A classe B acima não pode ser serializada pelo GSON. Como a classe B é uma classe interna (não estática), o GSON também não pode desserializar {"B": "ABC"} em uma instância da classe B. Se B for declarado como estática classe B, o GSON poderá desfazer a sequência.
Outra solução é escrever um criador de instância para B:
classe pública InstancecReAorForB implementa Instancecreator <B> {private final a a; public InstancECReAorForb (a a) {this.a = a; } public AB CreateInstance (tipo tipo) {return A.New B (); }}Este método é viável, mas não é recomendado. (O tradutor disse que não entendeu esse criador de instância e não sabia como usá -lo)
Exemplo: Array
Gson gson = new gson (); int [] ints = {1, 2, 3, 4, 5}; string [] strings = {"abc", "def", "ghi"}; // serializaçãogson.tojson (ints); ==> impressões [1,2,3,4,5] gson.tojson (strings); ==> Imprime ["ABC", "def", "ghi"] // DeserializationInt [] ints2 = gson.fromjson ("[1,2,3,4,5]", int []. classe); ==> ints2 será o mesmo que intsO GSON também suporta matrizes multidimensionais com tipos de dados complexos.
Exemplo: coleção
Gson gson = new gson (); coleção <TEGER> ints = lists.imtableList (1,2,3,4,5); // serializações de string json = gson.tojson (ints); // ==> JSON é [1,2,3,4,5] // DeserializationType Coleção
Limitações ao processar coleções:
Serialize/Desserialize genéricos
Ao usar Tojson (OBJ), o GSON chama obj.getclass () para obter informações de campo para uso em serialização. Da mesma forma, o objeto myclass.class pode ser passado como um parâmetro para o método Fromjson (json, myclass.class), que pode ser usado quando o objeto não é um genérico. No entanto, quando o objeto é um objeto de tipo genérico, as informações do tipo genérico serão perdidas devido ao mecanismo de apagamento do tipo em Java. O exemplo a seguir ilustra o seguinte:
classe foo <t> {t valor;} gson gson = new gson (); foo <ar> foo = new foo <ar> (); gson.tojson (foo); // não pode serializar serialize foo.value corretamente. // falha em desserializar foo.value como barraO código acima interpreta o valor como o tipo de barra, porque o GSON chama foo.getclass () para obter as informações da classe, mas esse método retorna uma classe primitiva, como foo.class. Isso significa que o GSON não pode saber que este é um objeto do tipo Foo <ar>.
Para resolver esse problema, você pode especificar o tipo parametrizado correto para seus genéricos. Você pode usar a classe TypeToken para fazer:
Tipo Footype = new TypeToken <Foo <ar >> () {} .gettype (); gson.tojson (foo, footype); gson.fromjson (json, footype);O Footype realmente define uma classe interna anônima, que contém um método getType () que pode retornar todos os tipos parametrizados.
Serialize/desserialize uma coleção de objetos de qualquer tipo
Às vezes, o JSON processado contém tipos mistos, como:
['Olá', 5, {Nome: 'Saudações', fonte: 'Guest'}]O conjunto correspondente deve ser:
Coleção de coleção = new ArrayList (); collection.add ("hello"); collection.add (5); collection.add (New Event ("Saudações", "Guest"));A classe de evento é definida da seguinte maneira:
Classe Evento {Nome da String Private; fonte de string privada; Evento privado (nome da string, fonte de string) {this.name = name; this.source = fonte; }}Com o GSON, você não precisa fazer nada de especial para serializar a coleção: Tojson (coleção) produzirá resultados satisfatórios.
No entanto, não é possível deserialização através de Fromjson (JSON, Coleção.class), porque o GSON não pode corresponder ao conteúdo em JSON com o tipo. O GSON exige que você forneça uma versão comum do tipo de coleção em Fromjson. Você tem três opções:
Solução 1: use a API do analisador GSON (analisador de fluxo de baixo nível ou o DOM Parser JSONPARSER) para analisar os elementos da matriz e, em seguida, use GSON.Fromjson () para processar cada elemento da matriz. Esta é a solução preferida.
Esquema 2: Registre um adaptador de tipo para coleção.class para mapear elementos na matriz no objeto apropriado. A desvantagem desse método é que ele causará inconvenientes ao lidar com outros tipos de coleta.
Esquema 3: Registre um adaptador de tipo para MyCollectionMemberType e use a coleção <MyCollectionMembertype> em Fromjson. Esse método só é possível se a matriz parecer um elemento de alto nível ou se você puder alterar o tipo de campo para a coleção <MyCollectionMemberType>.
Serializer/Deserializer embutido
O GSON fornece um serializador/desserializador para classes comumente usadas que podem não ser apropriadas para a representação padrão.
Aqui está uma lista dessas classes:
Serialização/deserialização personalizada
Às vezes, a implementação padrão do GSON não é o que você deseja, o que é mais comum ao lidar com algumas bibliotecas de classes (como o DateTime).
O GSON permite que você registre serializadores/desaperializadores personalizados. Para fazer isso, você precisa implementar as seguintes peças:
JSON Serializer: Precisa personalizar a serialização para um objeto
Deserializer JSON: você precisa personalizar o criador da classe de deserialização para um tipo: se houver um construtor sem parâmetros ou um desesteralizador foi registrado, não é necessário.
Gsonbuilder gson = new gsonbuilder (); gson.registertypeadapter (mytype2.class, new mytypeadapter ()); gson.registertypeadapter (mytype.class, new MySerializer ()); MyDeSerializer ()); GSON.RegisterTyPeadApter (mytype.class, new MyInstancecreator ());
O RegisterTyPeAdapter verifica se o adaptador de tipo implementa várias interfaces e registra o adaptador de tipo para essas interfaces.
Escreva um serializador
Aqui está um exemplo de personalização do serializador para o DateTime:
Classe privada DatetimeSerializer implementa o JSOnserializer <TateTime> {public JSonelement Serialize (DateTime SRC, Type TypeofSrc, JSOnserializationContext Context) {retorna novo jsonPrimitive (src.tostring ()); }}O GSON chama Tojson () ao serializar instâncias de DateTime.
Escreva um Deserializer
O exemplo a seguir mostra como escrever um desajeitador da classe DateTime:
Classe privada DATETImEDeSerializer implementa o JSondeSerializer <TateTime> {public DateTime Deserialize (JSonelement JSON, Type Typeoft, JSondeSerializationContext Context) lança jsonparseException {return dateTime (json.getasjsonPrimitive (). GetString (); }}Quando o GSON precisa desserializar uma string json para um objeto DateTime, dejson () será chamado.
Para serializadores/desaperizadores, deve -se prestar atenção a:
Escreva um criador de instância
Ao desapegar um objeto, o GSON precisa criar uma instância de uma classe. Uma classe que tem um bom desempenho durante a serialização/desserialização significa que essa classe possui um construtor sem parâmetros. Normalmente, ao lidar com classes sem construtores sem parâmetros em uma biblioteca de classes, é necessário um criador de instância.
Exemplo de criador de exemplo:
classe privada MoneyInstanceCreator implementa Instancecreator <Money> {public Money CreateInstance (tipo tipo) {Return New Money ("1000000", moedacode.usd); }}Criador de instância de tipo parametrizado
Às vezes, o tipo a ser instanciado será um tipo parametrizado. No geral, como a instância real é um tipo primitivo, isso não é um problema. Aqui está um exemplo:
classe MyList <T> estende o ArrayList <T> {} classe myListInstanceCreator implementa Instancecreator <MyList <? >> {@suppresswarnings ("não -controlado") public mylist <?> createInstance (tipo de tipo) {// Não é necessário usar uma lista de parâmetros. retornar new myList (); }}No entanto, às vezes você precisa criar instâncias com base em tipos parametrizados reais. Nesse caso, você pode passar o parâmetro de tipo para o método CreateInstance. Aqui está um exemplo:
classe pública ID <T> {classe final privada <T> ClassOfID; Private Final Long Value; Public ID (classe <T> ClassOfID, Valor longo) {this.classofid = ClassofID; this.value = value; }} classe IDInStancecReator implementa InstancecRor <id <? >> {public Id <?> createInstance (tipo tipo) {type [] typeParameters = (((parameterizadoType) tipo) .getActualTyPearGuments (); TIPO IDTYPE = TypeParameters [0]; // ID possui apenas um tipo t de retorno T Tipo T parametrizado ((classe) idtype, 0L); }}No exemplo acima, uma instância da classe ID não pode ser criada sem passar o tipo verdadeiro para o tipo parametrizado. Podemos resolver esse problema passando o tipo de parâmetro para o método. Aqui, o objeto Type pode ser considerado como uma representação do tipo Java parametrizado de ID <Foo>, e a instância correspondente deve estar vinculada ao ID <Foo>. Como o ID da classe possui apenas um parâmetro T do parâmetro, usamos getActualTyPearGument () para retornar o 0º elemento da matriz de tipos, neste exemplo, foo.class.
Saída compacta vs bela saída
A saída padrão do JSON no GSON está no formato JSON compacto. Ou seja, não há personagens de espaço em branco extras em JSON. Portanto, não há espaço em branco entre o nome do campo e o valor do campo, entre os campos e entre os elementos da matriz na saída do JSON. Além disso, o campo nulo não será emitido (Nota: NULL será preservado nos objetos de coleta e matriz).
Se você deseja gerar mais lindamente, precisa usar o GSONBuilder para configurar instâncias do GSON. O JSONFORMATRADA não existe na API pública, portanto o cliente não pode definir as configurações de saída padrão. Agora, fornecemos apenas o JSONPrintFormatter, que por padrão tem 80 caracteres por linha, o indentação usa 2 caracteres e a margem direita é de 4 caracteres.
O exemplo a seguir mostra como obter uma instância do GSON para usar um JSONPrintFormatter em vez de usar o JSONCOMPACTFORMTER padrão.
Gson gson = new GsonBuilder (). SetPrettyPrinting (). Create (); String jsonOutput = GSON.TOJSON (SomeObject);
Objeto vazio
Na implementação padrão do GSON, os objetos nulos são ignorados. Isso pode tornar o formato de saída (que pode ser considerado como resultado da serialização) mais apertado; No entanto, o cliente deve definir um valor padrão para que o JSON possa desfazer normalmente.
Se você quiser fazer um NULL serializável por instância GSON, você pode:
Gson gson = new gsonbuilder (). Serializenulls (). Create ();
Observe que, ao serializar nulo, um elemento jsonnull será adicionado à estrutura do JSonelement. Portanto, podemos usar esse objeto (GSON) em nosso serializador/desesterializador personalizado.
Aqui está um exemplo:
classe pública Foo {private final String s; private final int i; public Foo () {this (null, 5); } public foo (string s, int i) {this.s = s; this.i = i; }} Gson gson = new gsonbuilder (). Serializenulls (). Create (); foo foo = new foo (); string json = gson.tojson (foo); system.out.println (json); json = gson.tojson (null); system.out.println (json);Saída:
{"s": null, "i": 5} nuloSuporte de versão
Você pode usar a anotação @since para manter várias versões do mesmo objeto. Esta anotação pode ser usada em classes e campos e também será suportada nos métodos no futuro. Para usar esse recurso, você precisa configurar a instância do GSON para ignorar campos e objetos maiores que um determinado número da versão. Se a versão não estiver definida no objeto GSON, todos os campos e classes serão usados ao serializar/desapegar.
classe pública versãoEdClass {@Since (1.1) Private final String Newerfield; @Since (1.0) String final privada Newfield; campo de string final privado; public versãoEdClass () {this.newerfield = "mais recente"; this.newfield = "new"; this.field = "Old"; }} VersãoEdClass versionEdObject = new VersionEdClass (); GSON GSON = new GsonBuilder (). Setversion (1.0) .Create (); String jsonOutput = GSON.TOJSON (ALGOBJECT); GSON.OUT.println (jsonOut); System.out.println; GSON.TOJSON (ALGOBJETO); SYSTEM.OUT.println (JsonOutput);Saída:
{"Newfield": "New", "Field": "Old"} {"Newerfield": "Newer", "Newfield": "Now", "Field": "Old"}Excluir campos da serialização/deserialização
O GSON suporta o uso de muitos métodos para remover classes, campos e tipos de campo. Se o método a seguir não atender às suas necessidades, você poderá usar o método de serialização/desesterializador personalizado.
1.Java Modificador Exclusão
Por padrão, se um campo for declarado como transitório, o campo será excluído. Além disso, se um campo for declarado estático, esse campo também será excluído por padrão. Se você deseja incluir alguns campos declarados como transitórios, pode fazer isso:
importar java.lang.reflect.modifier; gson gson = new gsonbuilder () .excludeFieldsWithModifiers (modifier.static) .create ();
Observe que, no método excludeFieldsWithModifiers, você pode usar o maior número possível de constantes de modificador. Por exemplo:
Gson gson = new gsonbuilder () .excludeFieldsWithModifiers (modifier.static, modifier.transient, modifier.volatile) .create ();
2. Use o campo @Expospos para excluir
Esse recurso permite marcar campos específicos na classe para que eles não sejam excluídos/excluídos em serialização/deserialização. Para usar esta anotação, você deve criar um GSON usando o novo GsonBuilder (). ExcludeFieldsWithoutExposeanNotation (). Create (). A instância do GSON excluirá todos os campos da classe que não são marcados pelo @Expose.
3. Política de exclusão definida pelo usuário
Se o método de exclusão acima não puder atender às necessidades, você também poderá personalizar sua estratégia de exclusão. Para obter mais informações, consulte o Exclusionstrategy Javadoc.
O exemplo a seguir mostra como excluir campos marcados com @foo e excluir tipos de nível superior de classe de string ou tipos de campo declarados:
@Retention (retentionpolicy.runtime) @target ({elementType.field}) public @interface foo {// tag de campo apenas anotação} classe pública SampleObjectEstest {@foo private final int anotatedfield; String String String privado; Longfield privado final; Clazzfield da classe final privada <?>; public SampleObjectfortest () {annotatedfield = 5; stringfield = "SOMEDefaultValue"; Longfield = 1234; }} classe pública myExclusionstrategy implementa exclusões -estratégia {classe final privada <?> typeToSKIP; Private myExclusionstrategy (classe <?> typeToSkip) {this.typetoskip = typetoskip; } public boolean TOURSKIPCLASS (classe <?> clazz) {return (clazz == typetoskip); } público booleano }} public static void main (string [] args) {gson gson = new gsonbuilder () .SetexClusionstrategies (new MyExclusionstrategy (string.class)) .SerializEnulls () .Create (); SampleObjectfortest src = new samsebjectfortest (); String json = gson.tojson (src); System.out.println (JSON); }Saída:
{"Longfield": 1234}Apoio à nomeação de campo JSON
Algumas estratégias de nomeação de campo predefinidas do GSON podem converter nomes de campo Java padrão (ou seja, nomenclatura de camelo, como SampleFieldNameinjava) em um nome de campo JSON (que é Sample_Field_Name_in_Java ou SampleFieldNameinjava). Para mais informações, consulte o FieldnamingPolicy.
O GSON também possui uma política baseada em anotação para permitir que os clientes personalizem os nomes dos campos. Sob essa estratégia, se um nome de campo ilegal for fornecido como valor anotado, o GSON lançará uma exceção de tempo de execução.
O exemplo a seguir mostra como usar essas duas estratégias de nomeação do GSON:
Classe privada SomeObject {@SerializedName ("Custom_naming") String final privada algum campo; String final privada Algumfield; public SomeObject (String A, String b) {this.omefield = a; this.bomeotherfield = b; }} AlgunsObject algumObject = new SomeObject ("Primeiro", "Second"); GSON GSON = new GsonBuilder (). SetfieldnamingPolicy (fieldnamingpolicy.upper_camel_case) .Create ();Saída:
{"Custom_naming": "First", "Someotherfield": "Second"}Se você deseja personalizar o nome, pode usar a anotação @SerializedName.
Estado de compartilhamento entre serializador e Deserializer
Às vezes, você precisará compartilhar o estado entre o serializador e o Deserializer, e pode usar os três métodos a seguir para atingir seu objetivo:
Os dois primeiros métodos não são seguros para roscas, o terceiro é.
Solução para o GSON analisando o erro nulo
Uma desvantagem do GSON é que ele não pode definir a substituição nula.
Só podemos substituir manualmente o nulo retornado pelo servidor em lotes. Quando a interface normal for definida, o servidor definitivamente não poderá retornar nulo, mas o resultado em segundo plano sempre parecerá nulo!
Se você pesquisar, há uma resposta comum,
Gson gson = new gsonbuilder (). Serializenulls (). Create ();
Mas isso não pode resolver o problema de desamificação, como resolvê -lo?
A solução é a seguinte:
Gson gson = new gsonbuilder (). RegisterTyPeadApterFactory (new NullStringToEmptyAdApterFactory ()). Create (); // use o gson escrito na linha acima para serializar e merecer a classe de entidade tipegson.fromjson (json, tipo); gson. ajson (tipo de entidade NULT./ NullStringTOEmptyAdapterFactory <T> implementa o TypeAdApterFactory {@SuppressWarnings ("desmarcado") public <T> typeAdApter <T> CREATE (GSON GSON, TypeToken <T> tipo) {class <T> RAWTYPE = (classe <T>) Type.GeGrawType (); if (RawType! = String.class) {return null; } return (typeAdApter <T>) new StringNulladapter (); }} // StringNullAdapter Código public classe StringNulladapter estende o TypeAdApter <String> {@Override public String Read (JsonReader Reader) lança IoException {// TODO Auto-Generated Method Stub if (Reader.Peek () == Jsontoken.null) {Reader.Next.Nexl () retornar ""; } return reader.NextString (); } @Override public void Write (escritor jsonwriter, String Value) lança ioexception {// ToDO Method Method Stub if (value == null) {writer.nullValue (); retornar; } writer.value (valor); }}