天天看點

【json】與【枚舉】的序列化和反序列化

參考:​​Jackson – Deserialization from json to Java enums​​

問題描述

java中使用枚舉時,如果涉及到restful調用,不可避免會涉及到枚舉的序列化和反序列化工作;

如定義如下枚舉

public enum ResType {
  INSTANCE("虛拟機", "INSTANCE");

  private String name;
  private String type;

  ResType(String name, String type) {
    this.name = name;
    this.type = type;
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }


  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }
}      

上面代碼預設的序列化結果為:

{
        "resType": "INSTANCE"
}      

如果我們期望序列化的結果為:

{
        "resType": {
            "name": "虛拟機",
            "type": "INSTANCE"
        }
 }      

在需要修改上面的枚舉類,最簡單的方法是添加:​

​@JsonFormat(shape = JsonFormat.Shape.OBJECT)​

添加之後,序列化結果變為:更多的序列化可參考:​​官方序列化示例​​

{
        "resType": {
            "name": "虛拟機",
            "type": "INSTANCE"
        }
 }      

但此時若是使用上述結果進行​

​反序列化​

​操作,将會報錯,解決方式可參考文章頂部連結:即添加如下代碼

/**
   * 用于儲存所有的枚舉值
   */
  private static Map<String, ResType> RESOURCE_MAP = Stream
      .of(ResType.values())
      .collect(Collectors.toMap(s -> s.getType(), Function.identity()));


  /**
   * 枚舉反序列話調用該方法
   *
   * @param jsonNode
   * @return
   */
  @JsonCreator //必須修飾static方法
  public static ResType des(final JsonNode jsonNode) {
    return Optional
        .ofNullable(RESOURCE_MAP.get(jsonNode.get("type").asText()))
        .orElseThrow(() -> new IllegalArgumentException(jsonNode.get("type").asText()));
  }      
【json】與【枚舉】的序列化和反序列化

代碼

controller

@RestController
@RequestMapping("v1")
public class MyController {

  @Autowired
  private MyService myService;

  @GetMapping(value = "/my/model")
  public Response<?> endFloatingIpRateTask() {
    return Response.success(myService.getModel());
  }

  /**
   * 請求示例:
   * <pre>
   * {
   * "productId": "product01",
   * "resType": {
   *   "name": "虛拟機",
   *   "type": "INSTANCE"
   * }
   * }
   * </pre>
   *
   * @param taskResource
   * @return
   */
  @PostMapping(value = "/set/model")
  public Response<?> xxx(@RequestBody MyTaskResource taskResource) {
    System.out.println("xxxxxxxxxxxx");
    System.out.println(taskResource);
    System.out.println("xxxxxxxxxxxx");
    return Response.success(taskResource);
  }
}      

service

@Service
public class MyService {

  public MyTaskResource getModel() {
    MyTaskResource m = new MyTaskResource();
    m.setResType(ResType.INSTANCE);
    m.setProductId("product01");
    return m;
  }
}      
public class MyTaskResource {

  private String productId;
  private ResType resType;

  public ResType getResType() {
    return resType;
  }

  public void setResType(ResType resType) {
    this.resType = resType;
  }

  public String getProductId() {
    return productId;
  }

  public void setProductId(String productId) {
    this.productId = productId;
  }

  @Override
  public String toString() {
    return MoreObjects.toStringHelper(this)
        .add("productId", productId)
        .add("resType", resType)
        .toString();
  }
}      
@JsonFormat(shape = JsonFormat.Shape.OBJECT)
public enum ResType {
  INSTANCE("虛拟機", "INSTANCE");

  /**
   * 用于儲存所有的枚舉值
   */
  private static Map<String, ResType> RESOURCE_MAP = Stream
      .of(ResType.values())
      .collect(Collectors.toMap(s -> s.getType(), Function.identity()));
  private String name;
  private String type;

  ResType(String name, String type) {
    this.name = name;
    this.type = type;
  }

  /**
   * 枚舉反序列話調用該方法
   *
   * @param jsonNode
   * @return
   */
  @JsonCreator
  public static ResType des(final JsonNode jsonNode) {
    return Optional
        .ofNullable(RESOURCE_MAP.get(jsonNode.get("type").asText()))
        .orElseThrow(() -> new IllegalArgumentException(jsonNode.get("type").asText()));
  }

  public String getName() {
    return name;
  }

  public void setName(String name) {
    this.name = name;
  }


  public String getType() {
    return type;
  }

  public void setType(String type) {
    this.type = type;
  }
}      

測試結果