I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE COURSE

1. Overview

This quick tutorial will show how to control the way Java Enums are serialized to JSON output with Jackson 2.

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.

Further reading:

Jackson – Custom Serializer

Control your JSON output with Jackson 2 by using a Custom Serializer.

Read more

XML Serialization and Deserialization with Jackson

This short tutorial shows how the Jackson library can be used to serialize Java object to XML and deserialize them back to objects.

Read more

Jackson – Decide What Fields Get Serialized/Deserialized

How to control which fields get serialized/deserialized by Jackson and which fields get ignored.

Read more

2. Controlling the Enum Representation

Let’s define the following Enum:

public enum Distance {
    KILOMETER("km", 1000), 
    MILE("miles", 1609.34),
    METER("meters", 1), 
    INCH("inches", 0.0254),
    CENTIMETER("cm", 0.01), 
    MILLIMETER("mm", 0.001);

    private String unit;
    private final double meters;

    private Distance(String unit, double meters) {
        this.unit = unit;
        this.meters = meters;
    }

    // standard getters and setters
}

3. Default Enum Representation

By default, Jackson will represent Java Enums as simple String – for example:

new ObjectMapper().writeValueAsString(Distance.MILE);

Will result in:

"MILE"

What we would like to get when marshaling this ENUM to a JSON Object is to give something like:

{"unit":"miles","meters":1609.34}

4. Enum as Json Object

Starting with Jackson 2.1.2 – the is now a configuration option that can handle this kind of representation – via the @JsonFormat annotation, at the Enum level:

@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Distance { ... }

This will lead to the correct result when serializing this enum for Distance.MILE:

{"unit":"miles","meters":1609.34}

5. Enums and @JsonValue

Yet another simple way of controlling the marshaling output for an enum is using the @JsonValue annotation on a getter:

public enum Distance { 
    ...
 
    @JsonValue
    public String getMeters() {
        return meters;
    }
}

What we’re saying here is that getMeters() is the actual representation of this enum. So the result of serializing:

1609.34

6. Custom Serializer for Enum

Before Jackson 2.1.2, or if even more customization is required for the enum – we can use a custom Jackson serializer – first we’ll need to define it:

public class DistanceSerializer extends StdSerializer {
    
    public DistanceSerializer() {
        super(Distance.class);
    }

    public DistanceSerializer(Class t) {
        super(t);
    }

    public void serialize(Distance distance, JsonGenerator generator,
      SerializerProvider provider) 
      throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("name");
        generator.writeString(distance.name());
        generator.writeFieldName("unit");
        generator.writeString(distance.getUnit());
        generator.writeFieldName("meters");
        generator.writeNumber(distance.getMeters());
        generator.writeEndObject();
    }
}

We will now tie together the serializer and the class it applies to:

@JsonSerialize(using = DistanceSerializer.class)
public enum TypeEnum { ... }

The result:

{"name":"MILE","unit":"miles","meters":1609.34}

7. Conclusion

This article illustrated how to gain better control over the serialization process and format of Java Enums.

The implementation of all these examples and code snippets can be found over on Github – this is an Eclipse based project, so it should be easy to import and run as it is.

I just announced the new Spring 5 modules in REST With Spring:

>> CHECK OUT THE LESSONS

Sort by:   newest | oldest | most voted
TatuSaloranta
Guest

Good stuff. Two more suggestions for things to include: @JsonValue (serialize enum using value a method returns — yes, you can define custom methods for enum), and @JsonCreator for indicating factory method (that takes a single String arg) to use for reading Enums back.

Eugen Paraschiv
Guest

Hey Tatu – I was looking into using @JsonValue, but it looks like it’s not yet implemented: https://github.com/FasterXML/jackson-databind/issues/47
Let me know if your own experience is different with this one. Cheers,
Eugen.

TatuSaloranta
Guest

Well yes and no: yes, it is implemented for regular values; but no, not
when using Enums as keys of EnumMap (or Map).

Eugen Paraschiv
Guest

Sounds good Tatu – I updated the article – thanks for the heads up. Cheers,
Eugen.

Lukas Eder
Guest

Is there also a short form that uses Enum.name() and Enum.ordinal() as default implementations? I.e. that way, you don’t have to explicitly write the serialisation code…

Eugen Paraschiv
Guest

Hey Lukas. Yes – the default behaviour of Jackson does uses name() – so, if the name of the enum is enough, you don’t need to do anything else. In my examples, the name wasn’t enough because the enum also had an id.
Even so – you don’t need to write custom serialization – @JsonFormat would be enough.
The custom serializer is only for very specific requirements, where the standard object representation you would get from @JsonFormat isn’t enough either.
Hope that clarifies things. Cheers,
Eugen.

Lukas Eder
Guest

Great, thanks for the explanation

von
Guest

Please write about Jackson & GSON, which one should i use ?

Eugen Paraschiv
Guest

Without more context, I’m going to give you my personal preference – and that’s Jackson.

Kasim
Guest

Hi,
thank you very much for your helpful posts. But wouldn’t it be better to register the serializer to the object mapper. In this way you don’t need to write any jackson annotations within your domain model.
Regards,
Dino

Eugen Paraschiv
Guest

Hey Kasim – sure, a serializer is an option (see Section 6) – but it’s lower level so sometimes it’s easier to go with an annotation.

Ashwani kumar
Guest

Article is very clear & to the point. It is always very simple to understand from Eugen.