Estoy tratando de aprender Gson y estoy luchando con la exclusión de campo. Aqui estan mis clases
public class Student {
private Long id;
private String firstName = "Philip";
private String middleName = "J.";
private String initials = "P.F";
private String lastName = "Fry";
private Country country;
private Country countryOfBirth;
}
public class Country {
private Long id;
private String name;
private Object other;
}
Puedo usar GsonBuilder y agregar una ExclusionStrategy para un nombre de campo como firstName
o country
pero parece que no logro excluir propiedades de ciertos campos como country.name
.
Usando el método public boolean shouldSkipField(FieldAttributes fa)
, FieldAttributes no contiene suficiente información para hacer coincidir el campo con un filtro como country.name
.
PD: Quiero evitar anotaciones ya que quiero mejorar esto y usar RegEx para filtrar los campos.
Editar : estoy tratando de ver si es posible emular el comportamiento del complemento JSON Struts2
usando Gson
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
Editar: reabrí la pregunta con la siguiente adición:
Agregué un segundo campo con el mismo tipo para aclarar aún más este problema. Básicamente quiero excluir country.name
pero no countrOfBirth.name
. Tampoco quiero excluir País como tipo. Entonces, los tipos son los mismos, es el lugar real en el gráfico del objeto que quiero señalar y excluir.
fuente
JsonSerializer
para algún tipo,Country
en su caso, para el que luego se aplica yExclusionStrategy
que decide qué campos serializar.Respuestas:
Cualquier campo que no desee serializar en general, debe usar el modificador "transitorio", y esto también se aplica a los serializadores json (al menos a algunos que he usado, incluido gson).
Si no desea que el nombre aparezca en el json serializado, dele una palabra clave transitoria, por ejemplo:
Más detalles en la documentación de Gson
fuente
transient
lugar de@Expose
es que todavía tiene que simular un POJO en su cliente con todos los campos que podrían entrar. En el caso de una API de back-end que podría compartirse entre proyectos, esto podría ser problemático en caso de que Se agregan campos adicionales. Esencialmente es la lista blanca frente a la lista negra de los campos.Nishant proporcionó una buena solución, pero hay una manera más fácil. Simplemente marque los campos deseados con la anotación @Expose, como:
Omita los campos que no desee serializar. Luego, simplemente cree su objeto Gson de esta manera:
fuente
Por lo tanto, desea excluir
firstName
ycountry.name
. Así es comoExclusionStrategy
debería verseSi ve de cerca, devuelve
true
paraStudent.firstName
yCountry.name
, que es lo que desea excluir.Necesitas aplicar esto
ExclusionStrategy
así,Esto devuelve:
Supongo que el objeto país se inicializa
id = 91L
en la clase de estudiante.Puedes ponerte elegante. Por ejemplo, no desea serializar ningún campo que contenga una cadena de "nombre" en su nombre. Hacer esto:
Esto devolverá:
EDITAR: se agregó más información según lo solicitado.
Esto
ExclusionStrategy
hará lo necesario, pero debe pasar "Nombre de campo totalmente calificado". Vea abajo:Aquí es cómo podemos usarlo genéricamente.
Vuelve:
fuente
country.name
estrategia de exclusión que pueda tomar una cadena como y solo excluir el camponame
cuando se serializa el campocountry
. Debe ser lo suficientemente genérico como para aplicarse a cada clase que tenga una propiedad denominada country de la clase Country. No quiero crear una estrategia de exclusión para cada claseDespués de leer todas las respuestas disponibles, descubrí que lo más flexible, en mi caso, era usar
@Exclude
anotaciones personalizadas . Entonces, implementé una estrategia simple para esto (no quería marcar todos los campos usando@Expose
ni quería usar lostransient
que estaban en conflicto con laSerializable
serialización de la aplicación ):Anotación:
Estrategia:
Uso:
fuente
addSerializationExclusionStrategy
o enaddDeserializationExclusionStrategy
lugar desetExclusionStrategies
f.getAnnotation(Exclude.class) != null
af.getAnnotation(Exclude.class) == null
transient
debido a las necesidades de otras bibliotecas. ¡Gracias!Me encontré con este problema, en el que tenía una pequeña cantidad de campos que quería excluir solo de la serialización, por lo que desarrollé una solución bastante simple que usa la
@Expose
anotación de Gson con estrategias de exclusión personalizadas.La única forma integrada de usar
@Expose
es mediante la configuraciónGsonBuilder.excludeFieldsWithoutExposeAnnotation()
, pero como su nombre indica, los campos sin un explícito@Expose
se ignoran. Como solo tenía unos pocos campos que quería excluir, encontré la posibilidad de agregar la anotación a cada campo muy engorrosa.Efectivamente quería lo inverso, en el que todo estaba incluido a menos que explícitamente lo
@Expose
excluyera. Utilicé las siguientes estrategias de exclusión para lograr esto:Ahora puedo excluir fácilmente unos campos con
@Expose(serialize = false)
o@Expose(deserialize = false)
anotaciones (Nótese que el valor predeterminado para ambos@Expose
atributos estrue
). Por supuesto@Expose(serialize = false, deserialize = false)
, puede usarlo , pero eso se logra de manera más concisa al declarar el campo en sutransient
lugar (que todavía tiene efecto con estas estrategias de exclusión personalizadas).fuente
Puedes explorar el árbol json con gson.
Intenta algo como esto:
También puede agregar algunas propiedades:
Probado con gson 2.2.4.
fuente
Se me ocurrió una fábrica de clase para soportar esta funcionalidad. Pase cualquier combinación de campos o clases que desee excluir.
Para usar, cree dos listas (cada una es opcional) y cree su objeto GSON:
fuente
Resolví este problema con anotaciones personalizadas. Esta es mi clase de anotación "SkipSerialisation":
y este es mi GsonBuilder:
Ejemplo:
fuente
@Retention(RetentionPolicy.RUNTIME)
a su anotación.O puede decir qué campos no se expondrán con:
en su clase en atributo:
fuente
excludeFieldsWithModifiers()
eso.Utilicé esta estrategia: excluí todos los campos que no están marcados con la anotación @SerializedName , es decir:
Vuelve
fuente
Otro enfoque (especialmente útil si necesita tomar una decisión para excluir un campo en tiempo de ejecución) es registrar un TypeAdapter con su instancia de gson. Ejemplo a continuación:
En el siguiente caso, el servidor esperaría uno de los dos valores, pero dado que ambos eran ints, entonces gson los serializaría a ambos. Mi objetivo era omitir cualquier valor que sea cero (o menos) del json que se publica en el servidor.
fuente
La
@Transient
anotación de Kotlin también hace el truco aparentemente.Salida:
fuente
Estoy trabajando simplemente poniendo la
@Expose
anotación, aquí mi versión que usoEn
Model
clase:En la
Adapter
clase:fuente
Tengo la versión de Kotlin
y cómo puede agregar esto a Retrofit GSONConverterFactory:
fuente
Esto es lo que siempre uso:
El comportamiento predeterminado implementado en Gson es que los campos de objetos nulos se ignoran.
Significa que el objeto Gson no serializa campos con valores nulos a JSON. Si un campo en un objeto Java es nulo, Gson lo excluye.
Puede usar esta función para convertir algún objeto en nulo o bien configurado por usted mismo
fuente