Livro de receitas de serialização do Gson

Livro de receitas de serialização do Gson

Neste artigo, veremos os cenários mais comuns de serialização usandothe Gson library.

Vamos começar apresentandoa simple entity que usaremos nos seguintes exemplos:

public class SourceClass {
    private int intValue;
    private String stringValue;

    // standard getters and setters
}

1. Serializar uma matriz de entidades

Primeiro, vamos serializar uma matriz de objetos com Gson:

@Test
public void givenArrayOfObjects_whenSerializing_thenCorrect() {
    SourceClass[] sourceArray = {new SourceClass(1, "one"), new SourceClass(2, "two")};
    String jsonString = new Gson().toJson(sourceArray);

    String expectedResult =
      "[{"intValue":1,"stringValue":"one"},{"intValue":2,"stringValue":"two"}]";
    assertEquals(expectedResult, jsonString);
}

2. Serializar uma coleção de entidades

A seguir, vamos fazer o mesmo para uma coleção de objetos:

@Test
public void givenCollection_whenSerializing_thenCorrect() {
    Collection sourceCollection =
      Lists.newArrayList(new SourceClass(1, "one"), new SourceClass(2, "two"));
    String jsonCollection = new Gson().toJson(sourceCollection);

    String expectedResult =
      "[{"intValue":1,"stringValue":"one"},{"intValue":2,"stringValue":"two"}]";
    assertEquals(expectedResult, jsonCollection);
}

3. Alterar os nomes de campo de uma entidade na serialização

A seguir, vamos ver como podemoschange the name of the field quando estamos serializando uma entidade.

Vamos serializar nossa entidade, contendo os camposintValueestringValue para um json comotherIntValueeotherStringValue:

@Test
public void givenUsingCustomSerializer_whenChangingNameOfFieldOnSerializing_thenCorrect() {
    SourceClass sourceObject = new SourceClass(7, "seven");
    GsonBuilder gsonBuildr = new GsonBuilder();
    gsonBuildr.registerTypeAdapter(SourceClass.class, new DifferentNameSerializer());
    String jsonString = gsonBuildr.create().toJson(sourceObject);

    String expectedResult = "{"otherIntValue":7,"otherStringValue":"seven"}";
    assertEquals(expectedResult, jsonString);
}

Observe que estamos usando um serializador personalizado aqui para alterar o nome de nossos campos:

public class DifferentNameSerializer implements JsonSerializer {
    @Override
    public JsonElement serialize
      (SourceClass src, Type typeOfSrc, JsonSerializationContext context) {
        String otherIntValueName = "otherIntValue";
        String otherStringValueName = "otherStringValue";

        JsonObject jObject = new JsonObject();
        jObject.addProperty(otherIntValueName, src.getIntValue());
        jObject.addProperty(otherStringValueName, src.getStringValue());

        return jObject;
    }
}

4. Ignorar um campo ao serializar uma entidade

Vamos agoraignore a field completely ao realizar a serialização:

@Test
public void givenIgnoringAField_whenSerializingWithCustomSerializer_thenFieldIgnored() {
    SourceClass sourceObject = new SourceClass(7, "seven");
    GsonBuilder gsonBuildr = new GsonBuilder();
    gsonBuildr.registerTypeAdapter(SourceClass.class, new IgnoringFieldsSerializer());
    String jsonString = gsonBuildr.create().toJson(sourceObject);

    String expectedResult = "{"intValue":7}";
    assertEquals(expectedResult, jsonString);
}

Semelhante ao exemplo anterior, também estamos usando um serializador personalizado aqui:

public class IgnoringFieldsSerializer implements JsonSerializer {
    @Override
    public JsonElement serialize
      (SourceClass src, Type typeOfSrc, JsonSerializationContext context) {
        String intValue = "intValue";
        JsonObject jObject = new JsonObject();
        jObject.addProperty(intValue, src.getIntValue());

        return jObject;
    }
}

Observe também que provavelmente precisamos fazer isso nos casos em que não podemos alterar o código fonte da entidade ou se o campo deve ser ignorado apenas em casos muito específicos. Caso contrário, podemos ignorar o campo mais facilmente com uma anotação direta na classe da entidade.

5. Serializar um campo somente se passar por uma condição personalizada

Por fim, vamos analisar um caso de uso mais avançado - queremos serializar um campo apenas se ele passar por uma condição personalizada específica.

Por exemplo, vamos apenas serializar o valor int se for positivo e simplesmente ignorá-lo se for negativo:

@Test
public void givenUsingCustomDeserializer_whenFieldNotMatchesCriteria_thenIgnored() {
    SourceClass sourceObject = new SourceClass(-1, "minus 1");
    GsonBuilder gsonBuildr = new GsonBuilder();
    gsonBuildr.registerTypeAdapter(SourceClass.class,
      new IgnoringFieldsNotMatchingCriteriaSerializer());
    Gson gson = gsonBuildr.create();
    Type sourceObjectType = new TypeToken() {}.getType();
    String jsonString = gson.toJson(sourceObject, sourceObjectType);

    String expectedResult = "{"stringValue":"minus 1"}";
    assertEquals(expectedResult, jsonString);
}

Claro, estamos usandoa custom serializer aqui também:

public class IgnoringFieldsNotMatchingCriteriaSerializer
  implements JsonSerializer {
    @Override
    public JsonElement serialize
      (SourceClass src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject jObject = new JsonObject();

        // Criteria: intValue >= 0
        if (src.getIntValue() >= 0) {
            String intValue = "intValue";
            jObject.addProperty(intValue, src.getIntValue());
        }

        String stringValue = "stringValue";
        jObject.addProperty(stringValue, src.getStringValue());

        return jObject;
    }
}

E é isso - 5 casos de uso comuns deserialization using Gson.