标准化/结构化 JSON 输出

在构建一个基于JSON的API的时候, 往往我们还会需要添加一些额外的字段, 形成类似于 数据主体/额外信息 结构的数据, 如:

{
    "mainContent": { // 数据主体
        "name": "小明",
        "age": 11
    },
    "external": { // 额外信息
        "errorMsg": "OK",
        "errorCode": "0"
    }
}

方法1 建一个带泛型的 pojo , 将数据塞进去, 然后JSON化输出

这样的类可以是:

public class BizDto {
    
    public BizDto() {
        // 为了方便, 设置默认值
        External external = new External();
        external.setErrorCode("0");
        external.setErrorMsg("OK");
    }

    private T mainContent;
    private External external;

    public T getMainContent() {
        return mainContent;
    }

    public void setMainContent(T mainContent) {
        this.mainContent = mainContent;
    }

    public External getExternal() {
        return external;
    }

    public void setExternal(External external) {
        this.external = external;
    }

    public class External{
        private String errorMsg;
        private String errorCode;

        public String getErrorMsg() {
            return errorMsg;
        }

        public void setErrorMsg(String errorMsg) {
            this.errorMsg = errorMsg;
        }

        public String getErrorCode() {
            return errorCode;
        }

        public void setErrorCode(String errorCode) {
            this.errorCode = errorCode;
        }
    }
}

然后所有的 restfull api 都用这个 pojo 封装一下再输出

方法2 干预 spring json 序列化的过程

使用这个办法的好处是 controller 方法的返回值不需要做任何改变, 可以直接输出数据主体
先自定义HttpMessageConverter来实现自定义的 java转换过程 (from java/ to java)
然后呢 通过覆盖 spring 默认的 HttpMessageConverters, 或者将自己的 converter 加上去, 办法是声明一个 bean
@Bean
public HttpMessageConverters additionalConverters() {
return new HttpMessageConverters(new TheCustomConverter());
}

HttpMessageConverters 有3个构造方法

HttpMessageConverters(HttpMessageConverter... additionalConverters)
HttpMessageConverters(Collection> additionalConverters)
HttpMessageConverters(boolean addDefaultConverters, Collection> converters)

前两个是给spring 默认处理列表中添加一个新的 converter, 第三个是覆盖掉默认的 converters, 只使用自己定义的

使用这个方法还需要考虑一种情况, 就是出错了, 要怎么输出错误信息到前端

思路是使用@ControllerAdvice + 自定义 runtime Exception
遇到错误, 直接 throw new CustomeRuntimeException("errorcode","errormsg", ex)
交给框架去处理

小尾巴:
既然 spring 默认带了 jackson 作为 json 的序列化工具, 有没有人想过直接使用这个工具来序列化java对象呢, 多数时候我们都是再用一个第三方jar包比如著名的 fastJSON. 但再添加一个第三方工具带来的麻烦是 json 序列化时配置的不统一了
比如说 jackson 默认会将 Date 对象格式化成 utc 格式, 而fastJson会将日期输出成 毫秒 时间戳
有一个全局统一的配置, 可以避免在输出时每次都控制一下格式化, 而且很容易遗漏
办法就是, 注入 jackson 的ObjectMapper

    @Autowired
    private ObjectMapper objectMapper; // 注入
    // 输出JSON字符串
    objectMapper.writer().writeValueAsString(javaObj));
    // 将JSON字符串转成java bean;
    objectMapper.readValue(jsonStr,javaObj.class);

    Map map = new HashMap();
    // JSON string to Map
    map = objectMapper.readValue(json, new TypeReference>(){});


你可能感兴趣的:(标准化/结构化 JSON 输出)