0

In a JEE application, I created an enumeration with some custom label strings for the GUI:

public enum MyThing 
{
    THING1("Label 1"),
    ...
    THING5("Label 5");

    private String label;

    private MyThing(String label)
    {
        this.label = label;
    }
    ...
}

Objects with attributes of this enum type get delivered over a REST API. The attribute values get serialized as string IDs, wich is what I need:

Class with enum attribute:

public class MyBO
{
    private MyThing thing;
    ...
}

Service class:

import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
...

@Path("/bos")
public class MyBOsService
{
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public BO getBO()
    {
        BO bo = new BO();
        ...
        return bo;
    }
}

REST call result:

{"thing":"THING1",...}

Great! Now, however, I'd like to also deliver a complete list of IDs and labels through a different REST service class:

@Path("/masterdata")
public class MasterDataService
{
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    public MyThing[] allMyThings()
    {
        return MyThing.values();
    }
}

Desired REST call result:

[{"THING1":"Label 1"},{"THING2":"Label 2"}, ...]

I created a custom Jackson JsonSerializer to serialize the enum values as id-label pairs:

import org.codehaus.jackson.map.JsonSerializer;
...

public class MyThingSerializer extends JsonSerializer<MyThing>
{
    @Override
    public void serialize(MyThing myThing, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException
    {
    ...
    }
}

But now, I cannot find a sensible place to attach this JsonSerializer through an @JsonSerialize annotation. If I attach it to the enum like

@JsonSerialize(using = MyThingSerializer.class)
public enum MyThing{...

all enum values get serialized as id-label pairs, which is wrong for all REST calls but one.

If I attach it to the method supposed to deliver the list of id-value pairs, nothing happens:

@Path("/masterdata")
public class MasterDataService
{
    @GET
    @Produces(MediaType.APPLICATION_JSON)
    @JsonSerialize(using = MyThingSerializer.class)
    public MyThing[] allMyThings()
    {
        return MyThing.values();
    }
}

REST call result:

["THING1","THING2",...]

I know that I could attach the "id-label serializer" to the enum itself and then attach another serializer that restores the default serialization again to all other occurences of the enum, but is there a smarter way to achieve the desired different serializations in the different spots?

Joe7
  • 508
  • 1
  • 4
  • 17

1 Answers1

1

You can specify per-property custom serializers using @JsonSerialize(using=MySerializer.class).

In case of Lists and arrays, you will need to use:

@JsonSerialize(contentsUsing=MySerializer.class)

since using would replace serializer used for List or array itself; for values a different serializer is used.

StaxMan
  • 113,358
  • 34
  • 211
  • 239
  • This was sort of helpful, since this way I was pointed to the fact that I was using Jackson 1 while I should be using Jackson 2 to gain more functionality (e.g. the "contentsUsing" annotation element). Unfortunately, the result stays the same: Annotating the allMyThings() method with `@JsonSerialize(contentsUsing = MyThingSerializer.class)` still has no effect, the REST call result stays the same. I'm suspecting that you simply cannot serialize enum values on method level. – Joe7 May 04 '15 at 20:33
  • Looking at the original example, I suspect the reason is actually due to you annotating Resource method, and not value class. Handling for these differs because it happens outside of Jackson databind (Jackson is given a value, and not resource method, so it literally can not access those annotations). Now: this does not mean it can not be supported, but just that whatever handles calling of Jackson has to process annotations. With JAX-RS, the default Jackson JAX-RS provider (from https://github.com/FasterXML/jackson-jaxrs-providers) does support some of the annotations but... – StaxMan May 04 '15 at 21:35
  • .. but I don't remember if `@JsonSerialize`/`@JsonDeserialize` are yet supported (unlike `@JsonView` which is, for example). Make sure to use the latest version available (2.5.3), if possible. Otherwise use of array prevents some of the work-arounds (for example: if you had a `List`, you could create custom sub-class like `MyList`, annotate that type!); if possible, maybe consider using `Collection`/`List` sub-type, add annotation to that sub-class? – StaxMan May 04 '15 at 21:37