Let’s define the following Enum:
public enum Distance {
KILOMETER("km", 1000),
MILE("miles", 1609.34),
METER("meters", 1),
INCH("inches", 0.0254),
CENTIMETER("cm", 0.01),
MILLIMETER("mm", 0.001);
private String unit;
private final double meters;
private Distance(String unit, double meters) {
this.unit = unit;
this.meters = meters;
}
// standard getters and setters
}
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public enum Distance { ... }
new ObjectMapper().writeValueAsString(Distance.MILE);
结果
"MILE"
import com.fasterxml.jackson.annotation.JsonFormat;
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Distance { ... }
new ObjectMapper().writeValueAsString(Distance.MILE);
执行结果
{"unit":"miles","meters":1609.34}
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum Distance {
...
@JsonValue
public String getMeters() {
return meters;
}
}
new ObjectMapper().writeValueAsString(Distance.MILE);
执行结果
1609.34
发现:@JsonValue 优先级高于 @JsonFormat(shape = JsonFormat.Shape.OBJECT)
version of Jackson earlier than 2.1.2, or if even more customization is required for the enum, we can use a custom Jackson serializer.
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.std.StdSerializer;
import java.io.IOException;
public class DistanceSerializer extends StdSerializer<Distance> {
public DistanceSerializer() {
super(Distance.class);
}
@Override
public void serialize(Distance distance, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
jsonGenerator.writeStartObject();
jsonGenerator.writeFieldName("name");
jsonGenerator.writeString(distance.name());
jsonGenerator.writeFieldName("unit");
jsonGenerator.writeString(distance.getUnit());
jsonGenerator.writeFieldName("meters");
jsonGenerator.writeNumber(distance.getMeters());
jsonGenerator.writeEndObject();
}
}
@JsonSerialize(using = DistanceSerializer.class)
public enum Distance { ... }
public enum Distance { ... }
@Data
public class City {
private Distance distance;
}
City city = new City().setDistance(Distance.KILOMETER);
String s = new ObjectMapper().writeValueAsString(city);
System.out.println(s); // {"distance":"KILOMETER"}
String json = "{\"distance\":\"KILOMETER\"}";
City city1 = new ObjectMapper().readValue(json, City.class);
System.out.println(city1.toString()); // City(distance=KILOMETER)
do a case-insensitive deserialization
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
O
bjectMapper objectMapper = JsonMapper.builder()
.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
.build();
String json1 = "{\"distance\":\"KiLoMeTeR\"}";
City city2 = objectMapper.readValue(json1, City.class);
System.out.println(city2.toString()); // City(distance=KILOMETER)
public enum Distance {
...
@JsonValue
public double getMeters() {
return meters;
}
}
@Data
public class City {
private Distance distance;
}
import com.fasterxml.jackson.annotation.JsonValue;
String json3 = "{\"distance\":\"0.0254\"}";
City city3= new ObjectMapper().readValue(json3, City.class);
System.out.println(city3.toString()); // City(distance=INCH)
public enum Distance {
@JsonProperty("distance-in-km")
KILOMETER("km", 1000),
@JsonProperty("distance-in-miles")
MILE("miles", 1609.34);
...
}
@Data
public class City {
private Distance distance;
}
import com.fasterxml.jackson.annotation.JsonProperty;
String json = "{\"distance\":\"distance-in-km\"}";
City city1 = new ObjectMapper().readValue(json, City.class);
System.out.println(city1.toString()); // City(distance=KILOMETER)
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
public enum Distance {
@JsonCreator
public static Distance forValues(@JsonProperty("unit") String unit, @JsonProperty("meters") double meters) {
for (Distance distance : Distance.values()) {
if (distance.unit.equals(unit) && Double.compare(distance.meters, meters) == 0) {
return distance;
}
}
return null;
}
...
}
String json = "{\n" +
" \"distance\": {\n" +
" \"unit\":\"miles\", \n" +
" \"meters\":1609.34\n" +
" }\n" +
"}";
String json1 = "{" + "\"distance\": {" + "\"unit\":\"miles\", " + "\"meters\":1609.34" + "}" + "}";
City city1 = new ObjectMapper().readValue(json, City.class);
System.out.println(city1.toString()); // City(distance=MILE)
City city2 = new ObjectMapper().readValue(json1, City.class);
System.out.println(city2.toString()); // City(distance=MILE)
public class CustomEnumDeserializer extends StdDeserializer<Distance> {
@Override
public Distance deserialize(JsonParser jsonParser, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jsonParser.getCodec().readTree(jsonParser);
String unit = node.get("unit").asText();
double meters = node.get("meters").asDouble();
for (Distance distance : Distance.values()) {
if (distance.getUnit().equals(unit) && Double.compare(
distance.getMeters(), meters) == 0) {
return distance;
}
}
return null;
}
}
@JsonDeserialize(using = CustomEnumDeserializer.class)
public enum Distance {
...
}
-----------------------------------------------------------------------------读书笔记摘自 文章:How To Serialize and Deserialize Enums with Jackson