Estoy tratando de aprender Gson y estoy luchando con la exclusión de campo. Aquí están 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 el GsonBuilder y añadir una ExclusionStrategy para un nombre de campo como firstName
o country
pero parece que no puedo conseguir 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
.
Agradecería cualquier ayuda con una solución para este problema.
P.D: Quiero evitar las anotaciones ya que quiero mejorar esto y usar RegEx para filtrar los campos.
Gracias
Edición: Estoy intentando ver si es posible emular el comportamiento del plugin JSON de Struts2
usando Gson
<interceptor-ref name="json">
<param name="enableSMD">true</param>
<param name="excludeProperties">
login.password,
studentList.*\.sin
</param>
</interceptor-ref>
Edición: He reabierto la pregunta con el siguiente añadido:
He añadido un segundo campo con el mismo tipo para aclarar más este problema. Básicamente quiero excluir country.name
pero no countrOfBirth.name
. Tampoco quiero excluir País como tipo.
Por lo tanto, los tipos son los mismos, pero es el lugar real en el gráfico de objetos lo que quiero señalar y excluir.
Cualquier campo que no quieras serializar en general debes usar el modificador "transient", y esto también se aplica a los serializadores json (al menos lo hace con algunos que he usado, incluyendo gson).
Si no quieres que el nombre aparezca en el json serializado dale una palabra clave transient, ej:
private transient String name;
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:
@Expose private Long id;
Deja fuera los campos que no quieras serializar. A continuación, sólo tiene que crear su objeto Gson de esta manera:
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
Por lo tanto, usted quiere excluir nombre de pila
y nombre de país
. Esto es lo que su ExclusionStrategy
debe parecer
public class TestExclStrat implements ExclusionStrategy {
public boolean shouldSkipClass(Class<?> arg0) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
return (f.getDeclaringClass() == Student.class && f.getName().equals("firstName"))||
(f.getDeclaringClass() == Country.class && f.getName().equals("name"));
}
}
Si ves de cerca que devuelve true
para Student.firstName
y Country.name
, que es lo que quieres excluir.
Tienes que aplicar esta ExclusionStrategy
así,
Gson gson = new GsonBuilder()
.setExclusionStrategies(new TestExclStrat())
//.serializeNulls() <-- uncomment to serialize NULL fields as well
.create();
Student src = new Student();
String json = gson.toJson(src);
System.out.println(json);
Esto devuelve:
{ "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91}}
Supongo que el objeto país se inicializa con id = 91L
en la clase de estudiante.
Usted puede obtener de lujo. Por ejemplo, usted no quiere serializar cualquier campo que contiene "nombre" cadena en su nombre. Haga esto:
public boolean shouldSkipField(FieldAttributes f) {
return f.getName().toLowerCase().contains("name");
}
Esto devolverá:
{ "initials": "P.F", "country": { "id": 91 }}
EDIT: Se ha añadido más información según lo solicitado.
Este ExclusionStrategy
hará la cosa, pero usted necesita pasar "Fully Qualified Field Name". Ver abajo:
public class TestExclStrat implements ExclusionStrategy {
private Class<?> c;
private String fieldName;
public TestExclStrat(String fqfn) throws SecurityException, NoSuchFieldException, ClassNotFoundException
{
this.c = Class.forName(fqfn.substring(0, fqfn.lastIndexOf(".")));
this.fieldName = fqfn.substring(fqfn.lastIndexOf(".")+1);
}
public boolean shouldSkipClass(Class<?> arg0) {
return false;
}
public boolean shouldSkipField(FieldAttributes f) {
return (f.getDeclaringClass() == c && f.getName().equals(fieldName));
}
}
Aquí es cómo podemos utilizarlo genéricamente.
Gson gson = new GsonBuilder()
.setExclusionStrategies(new TestExclStrat("in.naishe.test.Country.name"))
//.serializeNulls()
.create();
Student src = new Student();
String json = gson.toJson(src);
System.out.println(json);
Devuelve:
{ "firstName": "Philip" , "middleName": "J.", "initials": "P.F", "lastName": "Fry", "country": { "id": 91 }}