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.