Search code examples
javajackson-databind

Jackson Enum format for the one you don't own


I am not able to find a way to serialize/deserialize an enum in my POJO. Most of the answers I found only deal with enum that you can change. I cannot change the enum.

Here is an example of my POJO.

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import javax.validation.constraints.NotNull;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.springframework.http.HttpStatus;

@Data
@NoArgsConstructor
@JsonInclude(Include.NON_NULL)
public class TitleRatingCheckItemResponse {
  private String titleId;

  @NotNull private Status status;

  @NoArgsConstructor
  @Data
  public static class Status {

    @NotNull
    private HttpStatus code;
  }
}

When I serialize the object to JSON, this is an example that I get

{
  "status": {
     "code": "OK"
  },
  "titleId": "titl_doc-1"
}

What I want to have is a JSON structure like the one below.

{
  "status": {
     "code": "200"
  },
  "titleId": "titl_doc-1"
}

To achieve the desired JSON output, I have to change HttpStatus. This is obvious not possible as I don't own the source code for HttpStatus. Is there any way I can do that?


Solution

    1. Create a class

      public class HttpStatusSerializer extends StdSerializer<HttpStatus> {
          public HttpStatusSerializer() {
              super(HttpStatus.class);
          }
      
          @Override
          public void serialize(HttpStatus value, JsonGenerator gen, SerializerProvider serializers) { 
              gen.writeString(String.valueOf(value.code())); // or whatever you want
          }
      }
      

      see StdSerializer docs. And another extending StdScalarDeserializer<HttpStatus>.

    2. Register it in your ObjectMapper, wherever you create it:

      ObjectMapper mapper = new ObjectMapper();    
      SimpleModule module = new SimpleModule();
      module.addSerializer(HttpStatus.class, new HttpStatusSerializer());
      module.addDeserializer(HttpStatus.class, new HttpStatusDeserializer());
      mapper.registerModule(module);
      

      Or if you want to use the custom serializer just for this field and not for all HttpStatuses:

      @NotNull
      @JsonSerialize(using=HttpStatusSerializer.class)
      @JsonDeserialize(using=HttpStatusDeserializer.class)
      private HttpStatus code;