Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Asymmetric serialization and deserialization using Jackson

I am using Jackson to serialize and deserialize data for a RESTful API. I'd like to have a REST resource (/comments) that allows to POST comments as well as to GET a list of comments.

Here's a (simplified) example of what gets posted to /comments.

{"text":"Text","author":"Paul","email":"[email protected]"}

Here's what the result of GET /comments should look like:

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

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

I have created a simple POJO class Comment that has fields with getters and setters for text, author, email, and emailHash.

Now, when I serialize the result, what I get is the following:

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

But I really don't like email to be returned as null here. It rather shouldn't be included at all.

Using the annotation @JsonIgnore on that field will also ignore it on deserialization. Do I have to create two classes, say CreationComment and ResultComment with a super-class Comment that shares common fields or is there a way that avoids creating additional classes?

like image 743
pvorb Avatar asked Feb 10 '23 04:02

pvorb


1 Answers

You don't have to create 2 classes at all. With Jackson you have full control of the behavior of a property during serialization and deserialization using annotations, with @JsonIgnorein the getter you prevent the property from being serialized in your Json response and using @JsonProperty annotation in the setter the property will be set 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 protected]");

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

            String json = "{\"author\":\"anAuthor\",\"email\":\"[email protected]\"}";
            Comment fromJson = objectMapper.readValue(json, Comment.class);

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

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

    }
}

The output after running the main() method to test the solution:

{"author":"anAuthor"}

Result from Json: author= anAuthor, email= [email protected]

Hope it helps,

Jose Luis

like image 160
jbarrueta Avatar answered Feb 13 '23 07:02

jbarrueta