I am using Jackson Marshaller for generating both XML and JSON from an object, but the JSON serialization of enum values always happens in capital letters.
I expected
{"handDrive": right}
but get
{"handDrive": RIGHT}
This is a snippet of my code...
@XmlType
@XmlEnum(String.class)
public enum HandDrive {
@XmlEnumValue("right")
RIGHT("right"), //
@XmlEnumValue("left")
LEFT("left");
}
ObjectMapper mapper = new ObjectMapper();
Car c = new Car();
c.setHandDrive(HandDrive.RIGHT);
mapper.setSerializationInclusion(Include.NON_NULL);
// convert Java object to JSON string
String jsonString = null;
try {
jsonString = mapper.writeValueAsString(c);
System.out.println(jsonString);
} catch (JsonProcessingException e) {
e.printStackTrace();
}
return jsonString;
Since your enum constants are provided with an argument, I assume you omitted a String
field and a one-arg constructor in the definition of HandDrive
when you posted your question.
By default, Jackson serializes enum values with the name of the corresponding constant. This is why the JSON produced contains RIGHT
or LEFT
. If you want to serialize an enum with one of its fields, you could either use the annotation @JsonValue
or a custom serializer.
By using @JsonValue
, you do not need XML annotations anymore. In fact, this annotation works for both JSON and XML serializations. To use it, just annotate the field value
or its getter getValue()
with it. Here is a demo at OneCompiler.
enum HandDrive {
RIGHT("right"),
LEFT("left");
@JsonValue
private String value;
HandDrive(String value) {
this.value = value;
}
// Alternatively here
// @JsonValue
public String getValue() {
return value;
}
}
If you do not want to use any annotation, you could define a custom serializer for the enum HandDrive
, and then register it as a module on both ObjectMapper
and XmlMapper
. Here is a demo at OneCompiler.
class HardDriveSerializer extends StdSerializer<HandDrive> {
public HardDriveSerializer(){
this(null);
}
public HardDriveSerializer(Class<HandDrive> t) {
super(t);
}
@Override
public void serialize(HandDrive value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(value.getValue());
}
}
public class Main {
public static void main(String[] args) {
Car c = new Car();
c.setHandDrive(HandDrive.RIGHT);
SimpleModule module = new SimpleModule();
module.addSerializer(HandDrive.class, new HardDriveSerializer());
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.registerModule(module);
try {
System.out.println(objectMapper.writeValueAsString(c));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(module);
try {
System.out.println(xmlMapper.writeValueAsString(c));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
enum HandDrive {
RIGHT("right"),
LEFT("left");
private String value;
HandDrive(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
In case you want to define a single custom serializer for any enum encountered during the marshalling process, you could make your custom serializer subtype Enum
, provide the name of a field to use as the serialization value, and then use reflection to retrieve the field's value. Here is a demo at OneCompiler.
public class EnumSerializer extends StdSerializer<Enum> {
private final String fieldName;
public EnumSerializer(String fieldName) {
this(null, fieldName);
}
public EnumSerializer(Class<Enum> t, String fieldName) {
super(t);
this.fieldName = fieldName;
}
@Override
public void serialize(Enum value, JsonGenerator gen, SerializerProvider provider) throws IOException {
try {
Field field = value.getClass().getDeclaredField(fieldName);
field.setAccessible(true);
gen.writeString(field.get(value).toString());
} catch (NoSuchFieldException | IllegalAccessException e) {
throw new RuntimeException(e);
}
}
}
public class Main {
public static void main(String[] args) {
Car c = new Car();
c.setHandDrive(HandDrive.RIGHT);
c.setHandDrive2(HandDrive2.DOWN);
SimpleModule module = new SimpleModule();
module.addSerializer(HandDrive.class, new EnumSerializer("value"));
module.addSerializer(HandDrive2.class, new EnumSerializer("otherValue"));
ObjectMapper mapper = new ObjectMapper();
mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
mapper.registerModule(module);
try {
System.out.println(mapper.writeValueAsString(c));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
XmlMapper xmlMapper = new XmlMapper();
xmlMapper.registerModule(module);
try {
System.out.println(xmlMapper.writeValueAsString(c));
} catch (JsonProcessingException e) {
throw new RuntimeException(e);
}
}
}
enum HandDrive {
RIGHT("right"),
LEFT("left");
private String value;
HandDrive(String value) {
this.value = value;
}
public String getValue() {
return value;
}
}
enum HandDrive2 {
UP("up"),
DOWN("down");
private String otherValue;
HandDrive2(String otherValue) {
this.otherValue = otherValue;
}
public String getOtherValue() {
return otherValue;
}
}