基于REST API的项目返回的数据结构题都是统一的,这样方便接口对接和使用。因此,对结果对象的设计会有一定的要求:
一个结果对象要能够同时支持成功和失败的数据结构;
要能够处理多种类的返回结果对象;
能够很轻易的判断出结果是成功还是失败;
能够存储错误编码和错误信息;
下面就基于Spring Boot项目来设计一下对应的统一结果返回对象。这里定义对应的类为ApiResponse:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.annotation.JsonValue; public final class ApiResponse<T> { private ErrorResponse error; private T data; private Status status; private ApiResponse(Status status, ErrorResponse error) { this.error = error; this.status = status; } private ApiResponse(Status status, T data) { this.data = data; this.status = status; } @JsonCreator public static <T> ApiResponse<T> success( @JsonProperty("status") Status status, @JsonProperty("data") T data) { return new ApiResponse<>(status, data); } @JsonCreator public static <T> ApiResponse<T> error( @JsonProperty("status") Status status, @JsonProperty("error") ErrorResponse error) { return new ApiResponse<>(status, error); } public enum Status { SUCCESS("success"), ERROR("error"); private final String status; Status(String status) { this.status = status; } @JsonValue public String getStatus() { return this.status; } } public ErrorResponse getError() { return this.error; } public T getData() { return this.data; } public Status getStatus() { return this.status; } }
上面的类有以下关键点:
- Status枚举类用来保存状态,这样可以方便的看出请求是成功还是失败;
- data变量使用了泛型,可以存储任何类型的对象;
- 错误信息可以通过error属性来获得;
ErrorResponse类内容如下:
import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; public final class ErrorResponse { public final String code; public final String message; @JsonCreator public ErrorResponse( @JsonProperty("code") String code, @JsonProperty("message") String message) { this.code = code; this.message = message; } }
ErrorResponse有code和message两个字段,code可以是http的返回编码也可以是任何业务编码。message变量用描述错误的信息。
基于上述对象,返回的JSON报文格式如下:
{ "status": "success", "data": { "task": "Write a post", "taskStatus":"in_progress", "tags":["writing"] } }
错误的报文如下:
{ "status": "error", "error": { "code" "409", "message" : "User with username xyz already exists" } }
需要注意的是JSON序列化时,需要排除结果为null的值。比如,在发生错误时,可能不希望data为null,如果使用的是Spring Boot框架,可以通过如下方式进行配置:
spring.jackson.default-property-inclusion=NON_NULL
1
如果使用的是Java 8或Gauva,想要要排除可选类型,则应使用NON_ABSENT值。
spring.jackson.default-property-inclusion=NON_ABSENT
1