Jackson Top

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE

1. Overview

This quick tutorial will show how to serialize a Java entity with Jackson 2 using a Custom Serializer.

If you want to dig deeper and learn other cool things you can do with the Jackson 2 – head on over to the main Jackson tutorial.

2. Standard Serialization of an Object Graph

Let's define 2 simple entities and see how Jackson serializes these without any custom logic:

public class User {
    public int id;
    public String name;
}
public class Item {
    public int id;
    public String itemName;
    public User owner;
}

Now, let's serialize an Item entity with a User entity:

Item myItem = new Item(1, "theItem", new User(2, "theUser"));
String serialized = new ObjectMapper().writeValueAsString(myItem);

This will result in a full JSON representation for both entities:

{
    "id": 1,
    "itemName": "theItem",
    "owner": {
        "id": 2,
        "name": "theUser"
    }
}

3. Custom Serializer on the ObjectMapper

Now, let's simplify the JSON output above by only serializing the id of the User, not the entire User object; we'd like to get the following, simpler JSON:

{
    "id": 25,
    "itemName": "FEDUfRgS",
    "owner": 15
}

Simply put, we'll have to define a custom Serializer for Item objects:

public class ItemSerializer extends StdSerializer<Item> {
    
    public ItemSerializer() {
        this(null);
    }
  
    public ItemSerializer(Class<Item> t) {
        super(t);
    }

    @Override
    public void serialize(
      Item value, JsonGenerator jgen, SerializerProvider provider) 
      throws IOException, JsonProcessingException {
 
        jgen.writeStartObject();
        jgen.writeNumberField("id", value.id);
        jgen.writeStringField("itemName", value.itemName);
        jgen.writeNumberField("owner", value.owner.id);
        jgen.writeEndObject();
    }
}

Now, we need to register this custom serializer with the ObjectMapper for the Item class, and perform the serialization:

Item myItem = new Item(1, "theItem", new User(2, "theUser"));
ObjectMapper mapper = new ObjectMapper();

SimpleModule module = new SimpleModule();
module.addSerializer(Item.class, new ItemSerializer());
mapper.registerModule(module);

String serialized = mapper.writeValueAsString(myItem);

That's it – we now have a simpler, custom JSON serialization of the Item->User entities.

4. Custom Serializer on the Class

We can also register the serializer directly on the class, instead of on the ObjectMapper:

@JsonSerialize(using = ItemSerializer.class)
public class Item {
    ...
}

Now, when performing standard serialization:

Item myItem = new Item(1, "theItem", new User(2, "theUser"));
String serialized = new ObjectMapper().writeValueAsString(myItem);

We will get the custom JSON output, created by the serializer, specified via @JsonSerialize:

{
    "id": 25,
    "itemName": "FEDUfRgS",
    "owner": 15
}

This is helpful when the ObjectMapper cannot be accessed and configured directly.

5. Conclusion

This article illustrated how to get to a custom JSON output with Jackson 2, by using Serializers.

The implementation of all these examples and code snippets can be found on GitHub – this is a Maven-based project, so it should be easy to import and run as it is.

Jackson bottom

I just announced the new Learn Spring course, focused on the fundamentals of Spring 5 and Spring Boot 2:

>> CHECK OUT THE COURSE
29 Comments
Oldest
Newest
Inline Feedbacks
View all comments
Stephane
Stephane
6 years ago

Hi Eugen, thanks for the Jackson series, I wonder how to put it to use in my demo Spring REST application for which I already use a ResourceAssemblerSupport class. You’d have an example where the two can play together ? Thanks.

Eugen Paraschiv
6 years ago
Reply to  Stephane

I haven’t yet written about spring-hateoas – but I do have it on my todo list – I’m bumping it up on the list if so that I get to it soon. Cheers,
Eugen.

Stephane
Stephane
6 years ago

No pressure… Thanks Eugen !

Stephane
Stephane
6 years ago

Or maybe it’s a contradiction in goals…

Stephane
Stephane
6 years ago

Hi Eugen,

It would be cool if your example here showed one object property as itself being a serialized object.

Cheers,

Stephane
Stephane
6 years ago
Reply to  Stephane

I think I found it. Simple.

jgen.writeObjectField(“address”, adminResource.getAddressResource());

Eugen Paraschiv
6 years ago
Reply to  Stephane

Yeah, that’s the way to write out an entire object – thanks for the note. Cheers,
Eugen.

cloudskol
cloudskol
5 years ago

Hi,
I am using Jackson library for my JSON serialization and de-serialization process. I would like to know how can I enforce a custom serialization property for a single property? I want to keep the remaining property by default. Whereas I need to change the transformation for one property. Is it possible without add the logic for all other properties?

Eugen Paraschiv
5 years ago
Reply to  cloudskol

I think I understand what you’re asking, but I’m not 100% sure – an example would be great. As a quick sidenote – if you need very granular control over the serialization and deserialziation processes – you’ll probably want to look at a custom Serializer/Deserializer. Cheers – and waiting for an example,
Eugen.

Maksim Murujev
Maksim Murujev
5 years ago

Will this work with Spring AMQP ??

Eugen Paraschiv
5 years ago
Reply to  Maksim Murujev

Well, AMQP is just the underlying protocol so it should work perfectly fine. That being said – I haven’t tried that combination before.

sprewell
sprewell
5 years ago

Hi! First of all, I´d like to thank you for your great tutorial. About this post, exists any way to create an annotation to use in fields, in order to use in a custom serilization? I mean, for example in the next POJO public class User { public int id; public String name; @IgnoreOnLog// custom annotation to avoid print this field in log public String pass; } Can I define a custom Serializer that i can use to write as string on loggers without print fields annotated with @IgnoreOnLog on any class? How it will be? Using GSON i have… Read more »

Comments are closed on this article!