hellzone
hellzone

Reputation: 5246

How to map multiple JsonProperty to a single variable?

I got a PrintType enum and I want to deserialize empty Strings as DEFAULT type like;

@JsonProperty("default", "")
DEFAULT

Is there any way to map multiple JsonProperty to a single variable?

My PrintType enum;

public enum PrintType{

    @JsonProperty("default")
    DEFAULT,


    ....

}

Upvotes: 3

Views: 4461

Answers (1)

Antot
Antot

Reputation: 3964

First of all, please note that JsonProperty is used to denote the names of properties, not their values. In this example, DEFAULT is an element of the enumeration, not its property/field/method, so this annotation would not be appropriate.

To deserialize an enum element from multiple possible values, you'll need to create a simple JsonDeserializer that will do the mapping. For example:

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;

import java.io.IOException;

public class PrintTypeDeserializer extends JsonDeserializer<PrintType> {

  private static final Set<String> DEFAULT_VALUES = new HashSet<>(Arrays.asList("", "default"));

  @Override
  public PrintType deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
    final String value = jsonParser.getValueAsString();
    if (DEFAULT_VALUES.contains(value)) {
      return PrintType.DEFAULT;
    }
    return PrintType.valueOf(value);
  }

}

To use this deserializer, either declare it on the PrintType field to be deserialized:

public class MyObj {

  @JsonProperty("print_type")
  @JsonDeserialize(using = PrintTypeDeserializer.class)
  private PrintType printType;

}

(But this would need to be duplicated if PrintType appears in different objects)

Or register the deserializer within the respective ObjectMapper:

private static ObjectMapper initObjectMapper() {
  final ObjectMapper mapper = new ObjectMapper();
  final SimpleModule module = new SimpleModule();
  module.addDeserializer(PrintType.class, new PrintTypeDeserializer());
  mapper.registerModule(module);
  return mapper;
}

Now, a short test case:

public enum PrintType {

  DEFAULT, TYPE_A, TYPE_B;

}

@Test
public void deserializeEnum() {
  final List<String> jsons = Arrays.asList(
      "{ \"print_type\": null }",
      "{ \"print_type\": \"\" }",
      "{ \"print_type\": \"default\" }",
      "{ \"print_type\": \"DEFAULT\" }",
      "{ \"print_type\": \"TYPE_A\" }",
      "{ \"print_type\": \"TYPE_B\" }"
  );

  final ObjectMapper mapper = initObjectMapper();

  jsons.stream().forEach(json -> {
    try {
      System.out.println(mapper.readValue(json, MyObj.class));
    } catch (IOException e) {
      throw new IllegalStateException(e);
    }
  });

}

// output:
//  MyObj(printType=null)
//  MyObj(printType=DEFAULT)
//  MyObj(printType=DEFAULT)
//  MyObj(printType=DEFAULT)
//  MyObj(printType=TYPE_A)
//  MyObj(printType=TYPE_B)

Upvotes: 2

Related Questions