GSON es una biblioteca Java utilizada para implementar la conversión mutua entre los objetos JSON y Java. GSON es un proyecto de código abierto alojado en https://github.com/google/gson.
La clase principal en GSON es GSON. También puede usar la clase GSONBuilder para establecer algunas opciones mientras crea objetos GSON.
Los objetos GSON no guardan ningún estado al procesar JSON, por lo que los usuarios pueden realizar fácilmente múltiples serialización, deserialización y otras operaciones en el mismo objeto GSON.
Ejemplo: uso básico
// Serializationgson gson = new Gson (); gson.tojson (1); // ==> Imprime 1GSON.TOJSON ("ABCD"); // ==> Imprime "ABCD" GSON.TOJSON (nuevo largo (10)); // ==> imprime 10int [] valores = {1}; gson.tojson (valores); // ==> imprime [1] // deserializationInt one = gson.fromjson ("1", int.class); integer one = gson.fromjson ("1", integer.class); long one = gson.fromjson ("1", integer.class); long one = gson.fromjson ("1" ", Long.class); gson.fromjson ("false", boolean.class); string str = gson.FromJson ("/" abc/"", string.class); string anotherstr = gson.fromjson ("[/" abc/"]", string.class); // singializationGogofprimitives obj = new bagOfPrimitives (); gson = neow gson (new gson (); Gson.tojson (OBJ); // ==> json es {"valor1": 1, "value2": "ABC"}Ejemplo: conversión entre un objeto y un JSON
Defina la clase BagOfPrimitiva:
clase BagOfPrimitive {private int value1 = 1; cadena privada value2 = "ABC"; Private Transitive Int Value3 = 3; BagOfPrimitivs () {// Constructor no-args}}Serializado a JSON:
// Serialization BaggOfPrimitivs obj = new BagOfPrimitives (); GSson Gson = new Gson (); String Json = Gson.tojson (OBJ); // ==> json es {"valor1": 1, "value2": "ABC"}No serialice objetos que contengan referencias circulares, de lo contrario se producirá una recursión infinita.
Deserialización:
// Deserialization BaggOfPrimitives obj2 = Gson.FromJson (JSON, BagOfPrimitivs.Class); // ==> obj2 es como obj
Algunos detalles al procesar objetos:
Manejo de clases anidadas (incluidas las clases internas)
GSON puede serializar fácilmente las clases anidadas y deserializar clases anidadas estáticas. GSON no puede deserializar automáticamente clases internas puras porque el constructor sin parámetros de la clase interna debe referirse al objeto que lo contiene (es decir, instancias de la clase exterior). Para deserializar una clase estática, puede estar estáticamente en la clase interna o proporcionar un creador de instancias personalizado. Aquí hay un ejemplo:
Clase pública A {Cadena pública a; Clase B {cadena pública B; public B () {// No Args Constructor para B}}}La clase B anterior no puede ser serializada por GSON. Dado que la clase B es una clase interna (no estática), GSON tampoco puede deserializar {"B": "ABC"} en una instancia de la clase B. Si B se declara como clase B está estática, entonces GSON puede deserializar la cadena.
Otra solución es escribir un creador de instancias para B:
clase pública InstancecreatorForb implementa Instancecreator <B> {Private Final A a; public instancecreatorfForB (a a) {this.a = a; } public ab CreateInstance (tipo tipo) {return a.new b (); }}Este método es factible, pero no se recomienda. (El traductor dijo que no entendía a este creador de instancia y que no sabía cómo usarlo)
Ejemplo: matriz
Gson gson = new Gson (); int [] ints = {1, 2, 3, 4, 5}; String [] Strings = {"ABC", "def", "Ghi"}; // SerializationGson.tojson (ints); ==> Imprime [1,2,3,4,5] Gson.tojson (cadenas); ==> imprime ["ABC", "def", "ghi"] // deserializationInt [] ints2 = gson.fromjson ("[1,2,3,4,5]", int []. class); ==> INTS2 será el mismo que INTSGSON también admite matrices multidimensionales con tipos de datos complejos.
Ejemplo: colección
Gson gson = new Gson (); colección <integer> ints = lists.immutableList (1,2,3,4,5); // SerializationString json = gson.tojson (ints); // ==> Json es [1,2,3,4,5] // deserializationType CollectionType = new typetoken <colección <integer> () {}. getType (); colección <integer> ints2 = gson.fromjson (json, colección type); // ints2 es igual que INTS INTSSLimitaciones al procesar colecciones:
Serializar/deserializar genéricos
Al usar TOJSON (OBJ), GSON llama a OBJ.GetClass () para obtener información de campo para su uso en la serialización. Del mismo modo, el objeto myclass.class se puede pasar como un parámetro al método fromjson (json, myclass.class), que se puede usar cuando el objeto no es genérico. Sin embargo, cuando el objeto es un objeto de tipo genérico, la información de tipo genérico se perderá debido al mecanismo de borrado de tipo en Java. El siguiente ejemplo ilustra esto:
clase foo <t> {t value;} gson gson = new gson (); foo <ar> foo = new foo <ar> (); gson.tojson (foo); // no puede serializar foo.value correctlygson.fromjson (json, foo.getclass ()); // no logra deserializar foo.value como barEl código anterior interpreta el valor como el tipo de barra, porque GSON llama a foo.getClass () para obtener la información de la clase, pero este método devuelve una clase primitiva, a saber, Foo.Class. Esto significa que GSON no puede saber que este es un objeto de tipo Foo <ar>.
Para resolver este problema, puede especificar el tipo parametrizado correcto para sus genéricos. Puede usar la clase TypeToken para hacer:
Type footype = new TypeToken <foo <ar> () {} .gettype (); gson.tojson (foo, tipo de pie); gson.fromjson (json, tipo de pie);El tipo de pie define una clase interna anónima, que contiene un método getType () que puede devolver todos los tipos parametrizados.
Serializar/deserializar una colección de objetos de cualquier tipo
A veces, el JSON procesado contiene tipos mixtos, como:
['Hola', 5, {nombre: 'Saludos', Fuente: 'Invitado'}]El conjunto correspondiente debe ser:
Colección colección = new ArrayList (); Collection.Add ("Hello"); Collection.Add (5); Collection.Add (nuevo evento ("Saludos", "Invitado"));La clase de evento se define de la siguiente manera:
evento de clase {nombre de cadena privada; fuente de cadena privada; evento privado (nombre de cadena, fuente de cadena) {this.name = name; this.source = fuente; }}Con GSON, no necesita hacer nada especial para serializar la colección: TOJSON (COLECCIÓN) generará resultados satisfactorios.
Sin embargo, la deserialización a través de JSON (JSON, Collection.Class) no es posible, porque GSON no puede corresponder al contenido en JSON con el tipo. GSON requiere que proporcione una versión común del tipo de colección desde JSON. Tienes tres opciones:
Solución 1: Use la API del analizador GSON (analizador de flujo de bajo nivel o el analizador DOM JSONPARSER) para analizar elementos de matriz, y luego use Gson.FromJson () para procesar cada elemento de matriz. Esta es la solución preferida.
Esquema 2: Registre un adaptador de tipo para colección. Class para mapear elementos en la matriz al objeto apropiado. La desventaja de este método es que causará inconvenientes cuando se trata de otros tipos de recolección.
Esquema 3: Registre un adaptador de tipo para MyCollectionMemberType y use Collection <MyCollectionMemberType> en Fromjson. Este método solo es posible si la matriz parece un elemento de alto nivel o si puede cambiar el tipo de campo a recolección <MyCollectionMemberType>.
Serializador/deserializador incorporado
GSON proporciona un serializador/deserializador para clases de uso común que puede no ser apropiado para la representación predeterminada.
Aquí hay una lista de estas clases:
Serialización/deserialización personalizada
A veces, la implementación predeterminada de GSON no es lo que desea, lo cual es más común cuando se trata de algunas bibliotecas de clases (como DateTime).
GSON le permite registrar serializadores/deserializadores personalizados. Para hacer esto, debe implementar las siguientes partes:
JSON Serializer: necesita personalizar la serialización para un objeto
JSON Deserializer: debe personalizar el creador de la clase de deserialización para un tipo: si hay un constructor sin parámetros o un deserializador se ha registrado, no es necesario.
GsonBuilder gson = new GsonBuilder (); gson.registerTypeadapter (mytype2.class, new myTypeadapter ()); gson.registerTypeadapter (mytype.class, nuevo myserializer ()); gson.registerTypeadapter (mytype.class, nuevo, nuevo nuevo MyDeserializer ()); gson.registerTypeadapter (mytype.class, new MyInStancEcreator ());
RegisterTypeAdapter verifica si el adaptador de tipo implementa múltiples interfaces y registra el adaptador de tipo para estas interfaces.
Escribe un serializador
Aquí hay un ejemplo de personalización del serializador para DateTime:
La clase privada dataTimesSerializer implementa JSonSerializer <Stetime> {public JSONElement Serialize (DateTime Src, Type TypeOfSrc, JSonSerializationContext Context) {return New JsonPrimitive (src.ToString ()); }}GSson llama a Tojson () al serializar las instancias de fecha y hora.
Escribe un deserializador
El siguiente ejemplo muestra cómo escribir un deserializador de la clase DateTime:
La clase privada DataTimedeserializer implementa JSondeserializer <Stetime> {Public DateTime Deserialize (JSONELEMENT JSON, Type TypeOft, JSondeserializationContext context) lanza JSONPARSEEXCECECION {return New DateTime (json.getAsjsonPrimitive (). getAstring ()); }}Cuando GSON necesita deserializar una cadena JSON a un objeto DateTime, se llamará deJSON ().
Para los serializadores/deserializadores, se debe prestar atención a:
Escribe un creador de instancias
Al deserializar un objeto, GSON necesita crear una instancia de una clase. Una clase que funciona bien durante la serialización/deserialización significa que esta clase tiene un constructor sin parámetros. Por lo general, cuando se trata de clases sin constructores sin parámetros en una biblioteca de clase, se requiere un creador de instancias.
Ejemplo de ejemplo de creador:
clase privada MoneyInstancecreator implementa Instancecreator <noney> {public Money CreateInstance (tipo tipo) {return New Money ("1000000", CurrencyCode.USD); }}Creador de instancia de tipo parametrizado
A veces, el tipo que se instancia será un tipo parametrizado. En general, dado que la instancia real es un tipo primitivo, esto no es un problema. Aquí hay un ejemplo:
Class MyList <T> extiende ArrayList <T> {} class myListinStancEcreator implementa instancecreator <mylist <? >> {@suppresswarnings ("sin verificar") public mylist <?> CreateInstance (tipo tipo) {// No es necesario usar una lista parametrizada ya que la instancia real tendrá el tipo crudo de todos modos. devolver nuevo mylist (); }}Sin embargo, a veces debe crear instancias basadas en tipos parametrizados reales. En este caso, puede pasar el parámetro Tipo al método CrearInstance. Aquí hay un ejemplo:
ID de clase pública <T> {clase final privada <t> classOfID; Valor largo de largo privado; ID pública (clase <T> classofid, Long Value) {this.classofid = classofid; this.Value = value; }} class IdinstancEcreator implementa InstancEcreator <id <? >> {public Id <?> CreateInstance (type type) {type [] typeParameters = ((parameterizedType) type) .getActualTypeArguments (); Type idtype = typeParameters [0]; // id tiene solo un tipo parametrizado t return id.get ((class) idtype, 0l); }}En el ejemplo anterior, no se puede crear una instancia de la clase ID sin pasar el tipo verdadero al tipo parametrizado. Podemos resolver este problema pasando el tipo de parámetro al método. Aquí, el objeto tipo se puede considerar como una representación del tipo de ID de Java parametrizado <foo>, y la instancia correspondiente debe estar vinculada a ID <foo>. Dado que la ID de clase solo tiene un parámetro t de parámetro, usamos getActualTyPearGument () para devolver el elemento 0th de la matriz de tipos, en este ejemplo, foo.class.
Salida compacta vs Beautiful Salida
La salida predeterminada de JSON en GSON está en formato JSON compacto. Es decir, no hay personajes de espacios blancos adicionales en JSON. Por lo tanto, no hay espacio en blanco entre el nombre del campo y el valor de campo, entre los campos y entre los elementos de matriz en la salida de JSON. Además, el campo NULL no se emitirá (Nota: NULL se conservará en los objetos de colección y matriz).
Si desea obtener más bellamente, debe usar GSONBuilder para configurar instancias GSON. JsonFormatter no existe en la API pública, por lo que el cliente no puede configurar la configuración de salida predeterminada. Ahora solo proporcionamos JSONPrintFormatter, que por defecto es 80 caracteres por línea, la sangría usa 2 caracteres y el margen derecho es 4 caracteres.
El siguiente ejemplo muestra cómo obtener una instancia de GSON para usar un JSONPrintFormatter en lugar de usar el JSONCompActformatter predeterminado.
Gson gson = new GsonBuilder (). SetPrettyPrinting (). Create (); String JsonOutput = Gson.ToJson (SomeObject);
Objeto vacío
En la implementación predeterminada de GSON, se ignoran los objetos nulos. Esto puede hacer que el formato de salida (que puede considerarse como el resultado de la serialización) más estricto; Sin embargo, el cliente debe definir un valor predeterminado para que JSON pueda deserializarse normalmente.
Si desea hacer una instancia de GSON serializable Null, puede:
Gson gson = new GsonBuilder (). Serializenulls (). Create ();
Tenga en cuenta que al serializar nulo, se agregará un elemento jsonnull a la estructura JSONELEMENT. Por lo tanto, podemos usar este objeto (GSON) en nuestro serializador/deserializador personalizado.
Aquí hay un ejemplo:
clase pública foo {cadena final privada 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.println (json); json = gson.tojson (null); system.println (json);Producción:
{"s": nulo, "i": 5} nuloSoporte de versión
Puede usar la anotación @Since para mantener múltiples versiones del mismo objeto. Esta anotación se puede utilizar en clases y campos, y también será compatible con métodos en el futuro. Para usar esta función, debe configurar la instancia de GSON para ignorar los campos y objetos más grandes que un número de versión determinado. Si la versión no se establece en el objeto GSON, todos los campos y clases se usan al serialización/deserialización.
clase pública VersionEdClass {@since (1.1) Private Final String Newerfield; @Since (1.0) String final privado Newfield; campo de cadena final privado; Public VersionEdClass () {this.newerfield = "nuevo"; this.newfield = "nuevo"; this.field = "antiguo"; }} VersionEdClass versionedObject = new VersionedClass (); gson gson = new GsonBuilder (). SetVersion (1.0) .Create (); String jsonoutput = gson.tojson (someObject); system.out.println (jsonoutput); system.println (); gson = new gson (); jsonoutput = gson.tojson (someObject); system.out.println (jsonoutput);Producción:
{"Newfield": "New", "Field": "Old"} {"Newerfield": "Newer", "Newfield": "New", "Field": "Old"}Excluir campos de la serialización/deserialización
GSON admite el uso de muchos métodos para eliminar clases, campos y tipos de campo. Si el siguiente método no satisface sus necesidades, puede usar el método de serialización/deserializador personalizado.
1. Exclusión del modificador de java
Por defecto, si se declara un campo como transitorio, el campo se excluye. Además, si un campo se declara estático, este campo también se excluirá de forma predeterminada. Si desea incluir algunos campos declarados como transitorios, puede hacer esto:
import java.lang.reflect.modifier; gson gson = new GsonBuilder () .excludeFieldsWithModifiers (modificador.static) .create ();
Tenga en cuenta que en el método excludfieldswithmodifiers, puede usar tantas constantes modificadoras como sea posible. Por ejemplo:
Gson gson = new GsonBuilder () .excludeFieldsWithModifiers (modificador.static, modifier.transient, modifier.volatile) .create ();
2. Use el campo @expose para excluir
Esta característica le permite etiquetar campos específicos en la clase para que no sean excluidos/excluidos en la serialización/deserialización. Para usar esta anotación, debe crear un GSON usando nuevo GSONBuilder (). ExcludeFieldswithoutExPoSeanNotation (). Create (). La instancia de GSON excluirá todos los campos de la clase que no están marcados por @expose.
3. Política de exclusión definida por el usuario
Si el método de exclusión anterior no puede satisfacer las necesidades, también puede personalizar su estrategia de exclusión. Para obtener más información, consulte ExclusionStrategy Javadoc.
El siguiente ejemplo muestra cómo excluir los campos marcados con @Foo y excluir tipos de clase de nivel superior o tipos de campo declarados:
@Retention (retenciónPolicy.Runtime) @Target ({elementType.field}) public @Interface foo {// Field Tag Only Annotation} public class SampleBjectFortest {@Foo Private Final Int AnnotatedField; String Final Stringfield privado; Longfield de Long Long privado; Clase final privada <?> Clazzfield; public speawObjectFortest () {annotatedField = 5; stringfield = "SomedefaultValue"; Longfield = 1234; }} clase pública myExClusionStrategy implementa exclusionStrategy {clase final privada <?> typetoskip; privado myExClusionStrategy (class <?> typetoskip) {this.typetoSkip = typetoskip; } public boolean debería skipclass (clase <?> clazz) {return (clazz == typetoskip); } public boolean deberskipfield (FieldAttributes f) {return f.getAnnotation (foo.class)! = null; }} public static void main (string [] args) {gson gson = new GsonBuilder () .setExClusionStrategies (new MyExClusionStrategy (String.Class)) .SerializizLs () .create (); SampleObjectFortest src = new SampleObjectFortest (); Cadena json = gson.tojson (src); System.out.println (JSON); }Producción:
{"Longfield": 1234}Soporte para nombres de campo JSON
Algunas estrategias de nomenclatura de campo predefinidas de GSON pueden convertir los nombres de campo Java estándar (es decir, la nomenclatura de camello, como SampleFieldNameInJava) en un nombre de campo JSON (que es sample_field_name_in_java o samplefieldnameInJava). Para obtener más información, consulte FieldnamingPolicy.
GSON también tiene una política basada en anotaciones para permitir a los clientes personalizar los nombres de los campos. Según esta estrategia, si se proporciona un nombre de campo ilegal como el valor anotado, GSON lanzará una excepción de tiempo de ejecución.
El siguiente ejemplo muestra cómo usar estas dos estrategias de nombres de GSON:
clase privada SomeObject {@SerializedName ("Custom_naming") String final privado SomeField; Cadena final privada Someotherfield; public someObject (String A, String B) {this.Somefield = a; this.yomeotherfield = b; }} SomeObject someObject = new SomeObject ("Primero", "Segundo"); GSson GSON = new GsonBuilder (). SetFieldNamingPolicy (FieldnamingPolicy.upper_camel_case) .Create (); String jsonRepresentation = gson.tojson (syleObject); system.out.println (jSonRepResentation);Producción:
{"Custom_naming": "Primero", "Someotherfield": "Segundo"}Si desea personalizar el nombre, puede usar la anotación @SerializedName.
Compartir estado entre serializador y deserializador
A veces deberá compartir el estado entre el serializador y el deserializador, y puede usar los siguientes tres métodos para lograr su objetivo:
Los dos primeros métodos no son seguros, el tercero es.
SOLUCIÓN AL ERROR NULL de análisis GSON
Una desventaja de GSON es que no puede establecer un reemplazo nulo.
Solo podemos reemplazar manualmente el nulo devuelto por el servidor en lotes. Cuando se define la interfaz normal, el servidor definitivamente no se le permitirá devolver nulo, ¡pero el resultado de fondo siempre aparecerá nulo!
Si busca, hay una respuesta común,
Gson gson = new GsonBuilder (). Serializenulls (). Create ();
Pero esto no puede resolver el problema de la desicencia, ¿cómo resolverlo?
La solución es la siguiente:
Gson gson = new GsonBuilder (). RegistroTyPeadApterFactory (new NullStringToEmptyAdapterFactory ()). Create (); // luego use el GSON escrito en la línea anterior para serializar y deserializar la clase de entidad Torgin.fromjson (json, type); gson.tojson (type); // nullstringtoptyadapterycefactory Classfactory NullStringToEmptyAdapterFactory <T> implementa typeadapterFactory {@supplesswarnings ("no dialeed") public <t> typeadapter <t> create (gson gson, typetoken <t> type) {class <t> rawType = (class <aT>) type.getrawType (); if (rawType! = string.class) {return null; } return (typeadapter <t>) new StringNullAdapter (); }} // Código de StringNullAdapter Class public StringNullAdapter extiende Typeadapter <String> {@Override public String Read (JSONReader Reader) lanza ioexception {// toDO Auto Generated Stub if (Reader.Peek () == JSonToken.Null) {Reader.nextNull (); devolver ""; } return Reader.nextString (); } @Override public void Write (JSONWriter Writer, String Value) lanza IOException {// TODO Auto Generado Método STUB if (value == NULL) {Writer.nullValue (); devolver; } escritor.value (valor); }}