Jackson – Serialize Enums as JSON Objects

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.

2. Controlling the Enum Representation

Let’s define the following Enum:

public enum Type {
    TYPE1(1, "Type A"), TYPE2(2, "Type 2");

    private Integer id;
    private String name;

    private Type(final Integer id, final String name) {
        this.id = id;
        this.name = name;
    }

    // standard getters and setters
}

3. Default Enum Representation

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

new ObjectMapper().writeValueAsString(Type.TYPE1);

Will result in:

"TYPE1"

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

{"name":"Type A","id":1}

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 Type { ... }

This will lead to the correct result when serializing the enum above:

{"name":"Type A","id":1}

5. Enums and @JsonValue

Yet another simple way of controlling the marshalling output for an enum is using the @JsonValue annotation:

public enum TypeEnumWithValue {
    TYPE1(1, "Type A"), TYPE2(2, "Type 2");

    private Integer id;
    private String name;

    private TypeEnumWithValue(final Integer id, final String name) {
        this.id = id;
        this.name = name;
    }

    ...

    @JsonValue
    public String getName() {
        return name;
    }
}

What we’re saying here is that getName is going to be the actual representation of this enum; so:

String enumAsString = mapper.writeValueAsString(TypeEnumWithValue.TYPE1);
assertThat(enumAsString, is("\"Type A\""));

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 TypeSerializer extends JsonSerializer<TypeEnum> {

    public void serialize
      (TypeEnumWithCustomSerializer value, JsonGenerator generator, SerializerProvider provider) 
      throws IOException, JsonProcessingException {
        generator.writeStartObject();
        generator.writeFieldName("id");
        generator.writeNumber(value.getId());
        generator.writeFieldName("name");
        generator.writeString(value.getName());
        generator.writeEndObject();
    }
}

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

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

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 in my github project – this is an Eclipse based project, so it should be easy to import and run as it is.

I usually post about Dev stuff on Google+ - you can follow me there:

>> GET THE EBOOKS <<
Get the eBooks and Learn to Build a Simple App
×
Build a Simple but Working App with Spring
  • TatuSaloranta

    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.

    • http://www.baeldung.com/ Eugen Paraschiv

      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

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

        • http://www.baeldung.com/ Eugen Paraschiv

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

  • http://www.jooq.org Lukas Eder

    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…

    • http://www.baeldung.com/ Eugen Paraschiv

      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.

      • http://www.jooq.org Lukas Eder

        Great, thanks for the explanation