Map Serialization and Deserialization with Jackson

来源:互联网 发布:开淘宝店进货渠道 编辑:程序博客网 时间:2024/06/11 04:13

1. Overview

In this article, we'll look at serialization and deserialization of Java maps using Jackson.

We'll illustrate how to serialize and deserialize Map<String, String>, Map<Object, String>, and Map<Object, Object> _to and from JSON-formatted _Strings.

2. Maven Configuration

<dependency>    <groupId>com.fasterxml.jackson.core</groupId>    <artifactId>jackson-databind</artifactId>    <version>2.8.7</version></dependency>

You can get the latest version of Jackson here.

3. Serialization

Serialization converts a Java object into a stream of bytes, which can be persisted or shared as needed. Java Maps are collections which map a key Object to a value Object and are often the least intuitive objects to serialize.

3.1. Map<String, String> Serialization

For the simple case, let's create a Map<String, String> and serialize it to JSON:

Map<String, String> map = new HashMap<>();map.put("key", "value");ObjectMapper mapper = new ObjectMapper();String jsonResult = mapper.writerWithDefaultPrettyPrinter()  .writeValueAsString(map);

ObjectMapper _is Jackson's serialization mapper, which allows us to serialize our _map and write it out as a pretty-printed JSON String, using the toString() method in String:

{  "key" : "value"}

3.2. Map<Object, String> Serialization

You can serialize a map containing a custom Java class with a few extra steps. Let's create a MyPair class to represent a pair of related String objects.

Note: the getters/setters should be public, and we annotate toString() _with @JsonValue to ensure Jackson uses this custom _toString() when serializing:

public class MyPair {    private String first;    private String second;    @Override    @JsonValue    public String toString() {        return first + " and " + second;    }    // standard getter, setters, equals, hashCode, constructors}

Now let's tell Jackson how to serialize MyPair by extending Jackson's JsonSerializer:

public class MyPairSerializer extends JsonSerializer<MyPair> {    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, as the name suggests, serializes MyPair to JSON using MyPair's toString() method. Jackson provides many Serializer classes to fit your serialization requirements.

We apply MyPairSerializer to our Map<MyPair, String> with the @JsonSerialize_annotation. Note that we've only told Jackson how to serialize _MyPair _because it already knows how to serialize _String:

@JsonSerialize(keyUsing = MyPairSerializer.class) Map<MyPair, String> map;

Let's test our map serialization:

map = new HashMap<>();MyPair key = new MyPair("Abbott", "Costello");map.put(key, "Comedy");String jsonResult = mapper.writerWithDefaultPrettyPrinter()  .writeValueAsString(map);

The serialized JSON output is:

{  "Abbott and Costello" : "Comedy"}

3.3. Map<Object, Object> Serialization

The most complex case is serializing a Map<Object, Object>, but most of the work is already done. Let's use Jackson's _MapSerializer _for our map, and _MyPairSerializer_from the previous section for the map's key and value types:

@JsonSerialize(keyUsing = MapSerializer.class)Map<MyPair, MyPair> map;@JsonSerialize(keyUsing = MyPairSerializer.class)MyPair mapKey;@JsonSerialize(keyUsing = MyPairSerializer.class)MyPair mapValue;

Let's test out serializing our Map<MyPair, MyPair>:

mapKey = new MyPair("Abbott", "Costello");mapValue = new MyPair("Comedy", "1940s");map.put(mapKey, mapValue);String jsonResult = mapper.writerWithDefaultPrettyPrinter()  .writeValueAsString(map);

The serialized JSON output, using MyPair's toString() method, is:

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

4. Deserialization

Deserialization converts a stream of bytes into a Java object that we can use in code. In this section, we'll deserialize JSON input into _Maps _of different signatures.

4.1. Map<String, String> Deserialization

For the simple case, let's take a JSON-formatted input string and convert it to a Map<String, String> Java collection:

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

We use Jackson's ObjectMapper as we did for serialization, using readValue() _to process the input. Also, note our use of Jackson's _TypeReference, which we'll use in all of our deserialization examples, to describe the type of our destination Map. Here is the _toString() _representation of our map:

{key=value}

4.2. Map<Object, String> Deserialization

Now, let's change our input JSON and the TypeReference _of our destination to_Map<MyPair, String>:

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

We need to create a constructor for MyPair that takes a String with both elements and parses them to the MyPair elements:

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

And the toString() of our Map<MyPair,String> object is:

{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 , one of many Deserialization classes that Jackson offers. We annotate our ClassWithAMap with @JsonCreator, @JsonProperty, and @JsonDeserialize:

public class ClassWithAMap {  @JsonProperty("map")  @JsonDeserialize(keyUsing = MyPairDeserializer.class)  private Map<MyPair, String> map;  @JsonCreator  public ClassWithAMap(Map<MyPair, String> map) {    this.map = map;  }  // public getters/setters omitted}

We are telling Jackson to deserialize the Map<MyPair, String> _contained in _ClassWithAMap, so we need to extend KeyDeserializer _to describe how to deserialize the map's key, a _MyPair _object, from an input _String:

public class MyPairDeserializer extends KeyDeserializer {  @Override  public MyPair deserializeKey(    String key,     DeserializationContext ctxt) throws IOException,     JsonProcessingException {      return new MyPair(key);    }}

We test the deserialization out using readValue:

String jsonInput = "{\"Abbott and Costello\":\"Comedy\"}";ClassWithAMap classWithMap = mapper.readValue(jsonInput,  ClassWithAMap.class);

Again, the toString() method of our ClassWithAMap's map gives us the output we expect:

{Abbott and Costello=Comedy}

4.3. Map<Object,Object> Deserialization

Lastly, let's change our input JSON and the TypeReference of our destination to Map<MyPair, MyPair>:

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

And the toString() of our Map<MyPair, MyPair> object is:

{Abbott and Costello=Comedy and 1940s}

5. Conclusion

In this quick tutorial, we've seen how to serialize and deserialize Java Maps to and from JSON-formatted Strings.

As always, you can check out the example provided in this article in the Github repository.

原文链接:http://www.baeldung.com/jackson-map

阅读全文
0 0