枚举类使用Jackson进行序列化与反序列化(How To Serialize and Deserialize Enums with Jackson)

逃离我推掉我的手 2024-03-23 00:19 191阅读 0赞

Let’s define the following Enum:

  1. public enum Distance {
  2. KILOMETER("km", 1000),
  3. MILE("miles", 1609.34),
  4. METER("meters", 1),
  5. INCH("inches", 0.0254),
  6. CENTIMETER("cm", 0.01),
  7. MILLIMETER("mm", 0.001);
  8. private String unit;
  9. private final double meters;
  10. private Distance(String unit, double meters) {
  11. this.unit = unit;
  12. this.meters = meters;
  13. }
  14. // standard getters and setters
  15. }

Serializing Enums to JSON

Default Enum Representation

  1. import com.fasterxml.jackson.core.JsonProcessingException;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. public enum Distance {
  4. ... }
  5. new ObjectMapper().writeValueAsString(Distance.MILE);
  6. 结果
  7. "MILE"

Enum as a JSON Object

  1. import com.fasterxml.jackson.annotation.JsonFormat;
  2. @JsonFormat(shape = JsonFormat.Shape.OBJECT)
  3. public enum Distance {
  4. ... }
  5. new ObjectMapper().writeValueAsString(Distance.MILE);
  6. 执行结果
  7. {
  8. "unit":"miles","meters":1609.34}

Enums and @JsonValue

  1. @JsonFormat(shape = JsonFormat.Shape.OBJECT)
  2. public enum Distance {
  3. ...
  4. @JsonValue
  5. public String getMeters() {
  6. return meters;
  7. }
  8. }
  9. new ObjectMapper().writeValueAsString(Distance.MILE);
  10. 执行结果
  11. 1609.34

发现:@JsonValue 优先级高于 @JsonFormat(shape = JsonFormat.Shape.OBJECT)

Custom Serializer for Enum

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.

  1. import com.fasterxml.jackson.core.JsonGenerator;
  2. import com.fasterxml.jackson.databind.SerializerProvider;
  3. import com.fasterxml.jackson.databind.ser.std.StdSerializer;
  4. import java.io.IOException;
  5. public class DistanceSerializer extends StdSerializer<Distance> {
  6. public DistanceSerializer() {
  7. super(Distance.class);
  8. }
  9. @Override
  10. public void serialize(Distance distance, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
  11. jsonGenerator.writeStartObject();
  12. jsonGenerator.writeFieldName("name");
  13. jsonGenerator.writeString(distance.name());
  14. jsonGenerator.writeFieldName("unit");
  15. jsonGenerator.writeString(distance.getUnit());
  16. jsonGenerator.writeFieldName("meters");
  17. jsonGenerator.writeNumber(distance.getMeters());
  18. jsonGenerator.writeEndObject();
  19. }
  20. }
  21. @JsonSerialize(using = DistanceSerializer.class)
  22. public enum Distance {
  23. ... }

Deserializing JSON to Enum

Default Behavior

  1. public enum Distance {
  2. ... }
  3. @Data
  4. public class City {
  5. private Distance distance;
  6. }
  7. City city = new City().setDistance(Distance.KILOMETER);
  8. String s = new ObjectMapper().writeValueAsString(city);
  9. System.out.println(s); // {"distance":"KILOMETER"}
  10. String json = "{\"distance\":\"KILOMETER\"}";
  11. City city1 = new ObjectMapper().readValue(json, City.class);
  12. System.out.println(city1.toString()); // City(distance=KILOMETER)

do a case-insensitive deserialization

  1. import com.fasterxml.jackson.databind.MapperFeature;
  2. import com.fasterxml.jackson.databind.ObjectMapper;
  3. import com.fasterxml.jackson.databind.json.JsonMapper;
  4. O
  5. bjectMapper objectMapper = JsonMapper.builder()
  6. .enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS)
  7. .build();
  8. String json1 = "{\"distance\":\"KiLoMeTeR\"}";
  9. City city2 = objectMapper.readValue(json1, City.class);
  10. System.out.println(city2.toString()); // City(distance=KILOMETER)

Using @JsonValue

  1. public enum Distance {
  2. ...
  3. @JsonValue
  4. public double getMeters() {
  5. return meters;
  6. }
  7. }
  8. @Data
  9. public class City {
  10. private Distance distance;
  11. }
  12. import com.fasterxml.jackson.annotation.JsonValue;
  13. String json3 = "{\"distance\":\"0.0254\"}";
  14. City city3= new ObjectMapper().readValue(json3, City.class);
  15. System.out.println(city3.toString()); // City(distance=INCH)

Using @JsonProperty

  1. public enum Distance {
  2. @JsonProperty("distance-in-km")
  3. KILOMETER("km", 1000),
  4. @JsonProperty("distance-in-miles")
  5. MILE("miles", 1609.34);
  6. ...
  7. }
  8. @Data
  9. public class City {
  10. private Distance distance;
  11. }
  12. import com.fasterxml.jackson.annotation.JsonProperty;
  13. String json = "{\"distance\":\"distance-in-km\"}";
  14. City city1 = new ObjectMapper().readValue(json, City.class);
  15. System.out.println(city1.toString()); // City(distance=KILOMETER)

Using @JsonCreator

  1. import com.fasterxml.jackson.annotation.JsonCreator;
  2. import com.fasterxml.jackson.annotation.JsonProperty;
  3. public enum Distance {
  4. @JsonCreator
  5. public static Distance forValues(@JsonProperty("unit") String unit, @JsonProperty("meters") double meters) {
  6. for (Distance distance : Distance.values()) {
  7. if (distance.unit.equals(unit) && Double.compare(distance.meters, meters) == 0) {
  8. return distance;
  9. }
  10. }
  11. return null;
  12. }
  13. ...
  14. }
  15. String json = "{\n" +
  16. " \"distance\": {\n" +
  17. " \"unit\":\"miles\", \n" +
  18. " \"meters\":1609.34\n" +
  19. " }\n" +
  20. "}";
  21. String json1 = "{" + "\"distance\": {" + "\"unit\":\"miles\", " + "\"meters\":1609.34" + "}" + "}";
  22. City city1 = new ObjectMapper().readValue(json, City.class);
  23. System.out.println(city1.toString()); // City(distance=MILE)
  24. City city2 = new ObjectMapper().readValue(json1, City.class);
  25. System.out.println(city2.toString()); // City(distance=MILE)

Using a Custom Deserializer

  1. public class CustomEnumDeserializer extends StdDeserializer<Distance> {
  2. @Override
  3. public Distance deserialize(JsonParser jsonParser, DeserializationContext ctxt)
  4. throws IOException, JsonProcessingException {
  5. JsonNode node = jsonParser.getCodec().readTree(jsonParser);
  6. String unit = node.get("unit").asText();
  7. double meters = node.get("meters").asDouble();
  8. for (Distance distance : Distance.values()) {
  9. if (distance.getUnit().equals(unit) && Double.compare(
  10. distance.getMeters(), meters) == 0) {
  11. return distance;
  12. }
  13. }
  14. return null;
  15. }
  16. }
  17. @JsonDeserialize(using = CustomEnumDeserializer.class)
  18. public enum Distance {
  19. ...
  20. }

-——————————————————————————————————————读书笔记摘自 文章:How To Serialize and Deserialize Enums with Jackson

发表评论

表情:
评论列表 (有 0 条评论,191人围观)

还没有评论,来说两句吧...

相关阅读