Asymmetric serialization and deserialization using Jackson

I am using Jackson to serialize and deserialize data for a RESTful API. I would like to have a REST ( /comments

) resource that allows POST comments as well as a list of comments.

Here's a (simplified) example of what is being sent to /comments

.

{"text":"Text","author":"Paul","email":"paul@example.org"}

      

Here's what the result GET /comments

should look like:

[{"text":"Text","author":"Paul","emailHash":"76w0kjKP9HpsdhBjx895Sg=="}]

      

Since the email addresses shouldn't be visible to anyone, I decided to return only the MD5 hash of the email addresses in the response.

I created a simple class is a POJO Comment

, which has fields with getters and setters for text

, author

, email

and emailHash

.

Now, when I serialize the result, I get this:

[{"text":"Text","author":"Paul","email":null,"emailHash":"76w0kjKP9HpsdhBjx895Sg=="}]

      

But I really don't like email

to return as quality null

here. It rather shouldn't be included at all.

Using annotation @JsonIgnore

in this field will also ignore it on deserialization. Should I create two classes, for example CreationComment

, and ResultComment

a superclass Comment

, which has a general field, or is there a way that avoids creating additional classes?

+3


source to share


2 answers


You don't need to create 2 classes at all. With Jackson, you have complete control over the behavior of the property during serialization and deserialization with annotations, when @JsonIgnore

in the getter you disable serialization of the property in your Json response and use the annotation @JsonProperty

in the setter, the property will be during deserialization. The code will look like this:

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Comment {

    private String author;

    private String email;

    @JsonIgnore
    public String getEmail() {
        return email;
    }

    @JsonProperty
    public void setEmail(String email) {
        this.email = email;
    }

    public String getAuthor() {
        return author;
    }

    public void setAuthor(String author) {
        this.author = author;
    }

    public static void main(String[] args) {
        ObjectMapper objectMapper = new ObjectMapper();

        Comment comment = new Comment();
        comment.setAuthor("anAuthor");
        comment.setEmail("email@example.com");

        try {
            System.out.println(objectMapper.writeValueAsString(comment));

            String json = "{\"author\":\"anAuthor\",\"email\":\"another@email.com\"}";
            Comment fromJson = objectMapper.readValue(json, Comment.class);

            System.out.println("Result from Json: author= " + fromJson.getAuthor() + ", email= " + fromJson.getEmail());

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

      

Exit after running the method main()

to test the solution:

{"author":"anAuthor"}



Result from Json: author= anAuthor, email= another@email.com

Hope it helps,

Jose Luis

+4


source


You can put @JsonIgnore

on getEmail

to prevent it from being serialized to JSON and use @JsonCreator

it to tell Jackson to the constructor to use for deserialization. The constructor will then only accept the property email

and will hash and assign your field emailHash

.

You can put annotation @JsonInclude

in your class Comment

to prevent serialization of fields null

.



Your class probably ends up looking something like this:

@JsonInclude(Include.NON_NULL)
public class Comment {
    private final String email;
    private final String emailHash;

    @JsonCreator
    public Comment(@JsonProperty("email") String email) {
        this.email = email;
        this.emailHash = MD5.hash(email);
    }

    @JsonIgnore
    public String getEmail() {
        return email;
    }

    public String getEmailHash() {
        return emailHash;
    }
}

      

+2


source







All Articles