Mapa de serialização e desserialização com Jackson

Mapa de serialização e desserialização com Jackson

1. Visão geral

Neste artigo, veremosserialization and deserialization of Java maps using Jackson.

Vamos ilustrar como serializar e desserializarMap<String, String>,Map<Object, String>, eMap<Object, Object> para e deStrings. formatado em JSON

2. Configuração do Maven


    com.fasterxml.jackson.core
    jackson-databind
    2.9.4

Você pode obter a versão mais recente de Jacksonhere.

3. Serialização

A serialização converte um objeto Java em um fluxo de bytes, que pode ser persistido ou compartilhado conforme necessário. JavaMaps são coleções que mapeiam uma chaveObject para um valorObject e geralmente são os objetos menos intuitivos para serializar.

3.1. Map<String, String> serialização

Para o caso simples, vamos criar umMap<String, String>e serializá-lo para JSON:

Map map = new HashMap<>();
map.put("key", "value");

ObjectMapper mapper = new ObjectMapper();
String jsonResult = mapper.writerWithDefaultPrettyPrinter()
  .writeValueAsString(map);

ObjectMapper é o mapeador de serialização de Jackson, que nos permite serializar nossomape escrevê-lo como um JSONString bem impresso, usando o métodotoString() emString:

{
  "key" : "value"
}

3.2. Map<Object, String> serialização

Você pode serializar um mapa contendo uma classe Java customizada com algumas etapas extras. Vamos criar uma classeMyPair para representar um par de objetosString relacionados.

Nota: os getters / setters devem ser públicos, e anotamostoString() com@JsonValue para garantir que Jackson use estetoString() personalizado ao serializar:

public class MyPair {

    private String first;
    private String second;

    @Override
    @JsonValue
    public String toString() {
        return first + " and " + second;
    }

    // standard getter, setters, equals, hashCode, constructors
}

Agora vamos dizer a Jackson como serializarMyPair estendendoJsonSerializer de Jackson:

public class MyPairSerializer extends JsonSerializer {

    private ObjectMapper mapper = new ObjectMapper();

    @Override
    public void serialize(MyPair value,
      JsonGenerator gen,
      SerializerProvider serializers)
      throws IOException, JsonProcessingException {

        StringWriter writer = new StringWriter();
        mapper.writeValue(writer, value);
        gen.writeFieldName(writer.toString());
    }
}

JsonSerializer, como o nome sugere, serializaMyPair em JSON usando o métodoMyPair'stoString(). Jackson fornece muitosSerializer classes para atender aos seus requisitos de serialização.

AplicamosMyPairSerializer ao nossoMap<MyPair, String> com a anotação@JsonSerialize. Observe que só dissemos a Jackson como serializarMyPair porque ele já sabe como serializarString:

@JsonSerialize(keyUsing = MyPairSerializer.class)
Map map;

Vamos testar nossa serialização de mapas:

map = new HashMap<>();
MyPair key = new MyPair("Abbott", "Costello");
map.put(key, "Comedy");

String jsonResult = mapper.writerWithDefaultPrettyPrinter()
  .writeValueAsString(map);

A saída JSON serializada é:

{
  "Abbott and Costello" : "Comedy"
}

3.3. Map<Object, Object> serialização

O caso mais complexo é serializar umMap<Object, Object>, mas a maior parte do trabalho já está feita. Vamos usarMapSerializer de Jackson para nosso mapa eMyPairSerializer da seção anterior para os tipos de chave e valor do mapa:

@JsonSerialize(keyUsing = MapSerializer.class)
Map map;

@JsonSerialize(keyUsing = MyPairSerializer.class)
MyPair mapKey;

@JsonSerialize(keyUsing = MyPairSerializer.class)
MyPair mapValue;

Vamos testar a serialização de nossoMap<MyPair, MyPair>:

mapKey = new MyPair("Abbott", "Costello");
mapValue = new MyPair("Comedy", "1940s");
map.put(mapKey, mapValue);

String jsonResult = mapper.writerWithDefaultPrettyPrinter()
  .writeValueAsString(map);

A saída JSON serializada, usando o métodoMyPair'stoString(), é:

{
  "Abbott and Costello" : "Comedy and 1940s"
}

4. Desserialização

A desserialização converte um fluxo de bytes em um objeto Java que podemos usar no código. Nesta seção, vamos desserializar a entrada JSON emMaps de assinaturas diferentes.

4.1. Map<String, String> desserialização

Para o caso simples, vamos pegar uma string de entrada formatada em JSON e convertê-la em uma coleção JavaMap<String, String>:

String jsonInput = "{\"key\": \"value\"}";
TypeReference> typeRef
  = new TypeReference>() {};
Map map = mapper.readValue(jsonInput, typeRef);

UsamosObjectMapper de Jackson como fizemos para a serialização, usandoreadValue() para processar a entrada. Além disso, observe nosso uso deTypeReference de Jackson, que usaremos em todos os nossos exemplos de desserialização, para descrever o tipo de nosso destinoMap. Aqui está a representaçãotoString() do nosso mapa:

{key=value}

4.2. Map<Object, String> desserialização

Agora, vamos mudar nosso JSON de entrada e oTypeReference de nosso destino paraMap<MyPair, String>:

String jsonInput = "{\"Abbott and Costello\" : \"Comedy\"}";

TypeReference> typeRef
  = new TypeReference>() {};
Map map = mapper.readValue(jsonInput, typeRef);

Precisamos criar um construtor paraMyPair que pegaString com ambos os elementos e os analisa para os elementosMyPair:

public MyPair(String both) {
    String[] pairs = both.split("and");
    this.first = pairs[0].trim();
    this.second = pairs[1].trim();
}

E otoString() do nosso objetoMap<MyPair,String> é:

{Abbott and Costello=Comedy}

There is another option for the case when we deserialize into a Java class that contains a Map — we can use Jackson’s KeyDeserializer class, uma das muitas classesDeserialization que Jackson oferece. Anotamos nossoClassWithAMap com@JsonCreator,@JsonProperty e@JsonDeserialize:

public class ClassWithAMap {

  @JsonProperty("map")
  @JsonDeserialize(keyUsing = MyPairDeserializer.class)
  private Map map;

  @JsonCreator
  public ClassWithAMap(Map map) {
    this.map = map;
  }

  // public getters/setters omitted
}

Estamos dizendo a Jackson para desserializar oMap<MyPair, String> contido emClassWithAMap, então precisamos estenderKeyDeserializer para descrever como desserializar a chave do mapa, um objetoMyPair, de uma entrada String:

public class MyPairDeserializer extends KeyDeserializer {

  @Override
  public MyPair deserializeKey(
    String key,
    DeserializationContext ctxt) throws IOException,
    JsonProcessingException {

      return new MyPair(key);
    }
}

Testamos a desserialização usandoreadValue:

String jsonInput = "{\"Abbott and Costello\":\"Comedy\"}";

ClassWithAMap classWithMap = mapper.readValue(jsonInput,
  ClassWithAMap.class);

Novamente, o métodotoString() de nosso mapaClassWithAMap’s nos dá a saída que esperamos:

{Abbott and Costello=Comedy}

4.3. Map<Object,Object> desserialização

Por último, vamos mudar nosso JSON de entrada e oTypeReference de nosso destino paraMap<MyPair, MyPair>:

String jsonInput = "{\"Abbott and Costello\" : \"Comedy and 1940s\"}";
TypeReference> typeRef
  = new TypeReference>() {};
Map map = mapper.readValue(jsonInput, typeRef);

E otoString() do nosso objetoMap<MyPair, MyPair> é:

{Abbott and Costello=Comedy and 1940s}

5. Conclusão

Neste tutorial rápido, vimos como serializar e desserializar JavaMaps de e para strings formatadas em JSON.

Como sempre, você pode verificar o exemplo fornecido neste artigo noGithub repository.