Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

356
Vistas
Gson: el parámetro se serializa aunque tenga @Expose(serialize = false)

Estoy escribiendo un SDK para una API JSON y me encuentro con un problema aparentemente extraño. La API es bastante estricta en su validación de datos POST y no permite que ciertos parámetros estén presentes al actualizar los recursos, como una id . Por esta razón, agregué @Expose(serialize = false) el campo ID de mi clase de recursos. Sin embargo, parece que todavía serializa este campo, lo que hace que se rechace la solicitud. La clase de recurso es aproximadamente la siguiente:

 public class Organisation extends BaseObject { public static final Gson PRETTY_PRINT_JSON = new GsonBuilder() .setPrettyPrinting() .create(); @Expose(serialize = false) @SerializedName("_id") private String id; @SerializedName("email") private String email; @SerializedName("name") private String name; @SerializedName("parent_id") private String parentId; public String toJson() { return PRETTY_PRINT_JSON.toJson(this); } }

Mis pruebas unitarias crean una instancia de Organisation a través de la API, guarda la instancia recién creada en la clase de prueba como un parámetro de clase y llama a un método de actualización que probará la implementación de actualización del SDK mediante la actualización del nuevo recurso. Aquí es donde sale mal. Aunque se llama al método toJson() en la nueva Organisation para serializarlo en JSON para la solicitud de actualización, el campo _id permanece presente, lo que hace que la API rechace la actualización. El código de prueba es el siguiente. Observe los comentarios en el código.

 @Test public void testCreateUpdateAndDeleteOrganisation() throws RequestException { Organisation organisation = new Organisation(); organisation.setParentId(this.ORGANISATION_ID); organisation.setName("Java Test Organisation"); Organisation newOrganisation = this.MySDK.organisation.create(organisation); this.testOrganisation(newOrganisation); this.newOrganisation = newOrganisation; this.testUpdateOrganisation(); } public void testUpdateOrganisation() throws RequestException { // I tried setting ID to null, but that doesn't work either // even though I've set Gson to not serialise null values this.newOrganisation.setId(null); this.newOrganisation.setName(this.newName); // For debugging System.out.println(this.newOrganisation.toJson()); Organisation updatedOrganisation = this.MySDK.organisation.update(this.newOrganisation.getId(), this.newOrganisation); this.testOrganisation(updatedOrganisation); assertEquals(newOrganisation.getName(), this.newName); this.testDeleteOrganisation(); }

¿Alguien puede detectar lo que estoy haciendo mal? Tengo la sensación de que tiene algo que ver con el hecho de que la instancia ya tiene/tenía un valor para ID, pero eso no debería importar si le digo explícitamente que no la serialice, ¿verdad?

Gracias de antemano por la ayuda.

EDITAR: En this.MySDK.organisation.update(this.newOrganisation.getId(), this.newOrganisation); , que no edita la instancia de la organización. La ID dada simplemente se agrega a la URL en la que el SDK publicará ( POST /organisation/{id} )

about 4 years ago · Santiago Trujillo
3 Respuestas
Responde la pregunta

0

Gracias a @peitek por señalar que @Expose se ignora a menos que se .excludeFieldsWithoutExposeAnnotation() a GsonBuilder() . Sin embargo, elijo no seguir esta ruta, ya que me obligaría a agregar @Expose a cada parámetro de mis clases modelo solo para ignorar un campo en la serialización. En su lugar, escribí una ExclusionStrategy que verifica la presencia de una anotación SkipSerialisation personalizada en el parámetro. Los implementé de la siguiente manera:

El GsonBuilder completo con la estrategia:

 public static final Gson PRETTY_PRINT_JSON = new GsonBuilder() .addSerializationExclusionStrategy(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { return f.getAnnotation(SkipSerialisation.class) != null; } @Override public boolean shouldSkipClass(Class<?> clazz) { return false; } }) .setPrettyPrinting() .create();

Y la anotación:

 @Retention(RetentionPolicy.RUNTIME) @Target(ElementType.FIELD) public @interface SkipSerialisation { }

Ahora solo puedo hacer

 @SkipSerialisation @SerializedName("_id") private String id;

¡y funciona!

about 4 years ago · Santiago Trujillo Denunciar

0

Como mencionó en sus comentarios, @Expose debería ser la mejor opción sobre transient aquí. ¡Es importante tener en cuenta que la instancia predeterminada de Gson no tiene en cuenta la anotación @Expose ! Simplemente lo ignorará, sin importar lo que establezca como opción.

Si desea activar las opciones de @Expose , debe personalizar Gson. Según su código anterior, cámbielo a:

 public static final Gson PRETTY_PRINT_JSON = new GsonBuilder() .setPrettyPrinting() .excludeFieldsWithoutExposeAnnotation(); .create();

Tu @Expose(serialize = false) debe estar activo y excluido durante la serialización.

about 4 years ago · Santiago Trujillo Denunciar

0

Solo quería agregar aquí que podría usar Expose de la manera deseada de esta manera:

 builder.addSerializationExclusionStrategy(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { Expose annotation = f.getAnnotation(Expose.class); if(annotation != null) return !annotation.serialize(); else return false; } @Override public boolean shouldSkipClass(Class<?> clazz) { Expose annotation = clazz.getAnnotation(Expose.class); if(annotation != null) return !annotation.serialize(); else return false; } }); builder.addDeserializationExclusionStrategy(new ExclusionStrategy() { @Override public boolean shouldSkipField(FieldAttributes f) { Expose annotation = f.getAnnotation(Expose.class); if(annotation != null) return !annotation.deserialize(); else return false; } @Override public boolean shouldSkipClass(Class<?> clazz) { Expose annotation = clazz.getAnnotation(Expose.class); if(annotation != null) return !annotation.deserialize(); else return false; } });
about 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda