首页 前端知识 json反序列化时泛型处理

json反序列化时泛型处理

2024-06-18 00:06:17 前端知识 前端哥 982 11 我要收藏

在对json字符串进行反序列化时,如果没有指定实体类中的泛型类型,那么反序列化出的对象对泛型内容有不同的处理:fastjson将泛型内容反序列化为它自己定义的 com.alibaba.fastjson.JSONObject;jackson反序列化为 java.util.LinkedHashMap;gson反序列化为 com.google.gson.internal.LinkedTreeMap。可见如果不进行泛型指定,反序列化出的对象交给其他的方法或接口使用时会有问题,其实常用的json处理框架对泛型都进行比较好的支持,可以在反序列化时就指定泛型的类型。下面就介绍一下如何使用:
我们需要提前定义好一些实体类。
定义泛型实体,这种实体类常用于接口返回数据:

import java.io.Serializable;

public class ApiResult<T> implements Serializable {

    /**
     * 响应状态码:200-成功;其他-失败
     */
    private int code;
    /**
     * 响应数据
     */
    private T data;
    /**
     * 响应结果描述
     */
    private String message = "";
    /**
     * 响应耗时:毫秒
     */
    private long time;

    public ApiResult() {

    }

    public ApiResult(T data) {
        this.data = data;
    }

    public ApiResult(int code, T data, String message) {
        this.code = code;
        this.data = data;
        this.message = message;
    }

    public int getCode() {
        return code;
    }

    public ApiResult setCode(int code) {
        this.code = code;
        return this;
    }

    public String getMessage() {
        return message;
    }

    public ApiResult setMessage(String message) {
        this.message = message;
        return this;
    }

    public T getData() {
        return data;
    }

    public ApiResult setData(T data) {
        this.data = data;
        return this;
    }

    public long getTime() {
        return this.time;
    }

    public ApiResult setTime(long time) {
        this.time = time;
        return this;
    }

    /**
     * 成功
     *
     * @return
     */
    public static ApiResult success() {
        ApiResult result = new ApiResult(StatusCode.C_200.getCode(), null, StatusCode.C_200.getMessage());
        return result;
    }

    /**
     * 成功
     *
     * @param data
     * @param <T>
     * @return
     */
    public static <T> ApiResult success(T data) {
        ApiResult result = new ApiResult(StatusCode.C_200.getCode(), data, StatusCode.C_200.getMessage());
        return result;
    }

    /**
     * 失败
     *
     * @param statusCode
     * @return
     */
    public static ApiResult fail(StatusCode statusCode) {
        return new ApiResult().setCode(statusCode.getCode()).setMessage(statusCode.getMessage());
    }

    /**
     * 异常
     *
     * @return
     */
    public static ApiResult error() {
        return new ApiResult().setCode(StatusCode.C_ERROR.getCode()).setMessage(StatusCode.C_ERROR.getMessage());
    }

    /**
     * 判断响应是否为成功响应
     *
     * @return
     */
    public boolean isSuccess() {
        if (this.code != 200) {
            return false;
        }
        return true;
    }

    public static ApiResult copyCodeAndMessage(ApiResult result) {
        return new ApiResult().setCode(result.getCode()).setMessage(result.getMessage());
    }
}

定义一个状态枚举信息,将返回的所有状态都在这个枚举中列出:

/**
 * 状态枚举
 */
public enum StatusCode {
    /**
     * 正常
     */
    C_200(200, "success"),
    /**
     * 系统繁忙
     */
    C_ERROR(-1, "系统繁忙"),
    /**
     * 特殊错误信息
     */
    C_10000(10000, "特殊错误信息"),
    /**
     * 用户未登录
     */
    C_10001(10001, "用户未登录"),
    /**
     * 用户无访问权限
     */
    C_10002(10002, "用户无访问权限"),
    /**
     * 用户身份验证失败
     */
    C_10003(10003, "用户身份验证失败"),
    /**
     * 请求参数错误
     */
    C_10004(10004, "请求参数错误"),
    /**
     * 请求信息不存在
     */
    C_10005(10005, "请求信息不存在"),
    /**
     * 更新数据失败
     */
    C_10006(10006, "更新数据失败"),
    ;

    private Integer code;
    private String message;

    StatusCode(int code, String message) {
        this.code = code;
        this.message = message;
    }

    public Integer getCode() {
        return code;
    }

    public String getMessage() {
        return message;
    }

    public static StatusCode getByCode(int code) {
        StatusCode[] values = StatusCode.values();
        for (StatusCode value : values) {
            if (code == value.code) {
                return value;
            }
        }
        return StatusCode.C_ERROR;
    }

}

在定义一个类用于表示返回的数据:

import lombok.AllArgsConstructor;
import lombok.Builder;
import lombok.Data;
import lombok.NoArgsConstructor;

@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class DemoVo {

    private int id;
    private String name;
    private String address;
}

以下所有的json反序列化操作都是基于下面的字符串:

{"code":200,"data":{"address":"guangdong-shenzhen-nanshan","id":123,"name":"xingo"},"message":"success","time":0}
  1. fastjson
    fastjson处理泛型比较简单,只需要定义需要泛型处理的 com.alibaba.fastjson.TypeReference 就可以,一段代码实现:
ApiResult<DemoVo> api = JSONObject.parseObject(json, new TypeReference<ApiResult<DemoVo>>() {});

也可以先定义一个 java.lang.reflect.Type,然后再使用这个Type:

Type type = new TypeReference<ApiResult<DemoVo>>() {}.getType();
ApiResult<DemoVo> api = JSONObject.parseObject(json, type);
  1. jackson
    jackson与fastjson类似,可以定义一个 com.fasterxml.jackson.core.type.TypeReference ,然后在反序列化时使用它:
ObjectMapper mapper = new ObjectMapper();
// 反序列化的时候如果多了其他属性,不抛出异常
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 如果是空对象的时候,不抛异常
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

// 指定引用的泛型
TypeReference<ApiResult<DemoVo>> type = new TypeReference<ApiResult<DemoVo>>(){};
ApiResult<DemoVo> api = mapper.readValue(json, type);

或者定义 com.fasterxml.jackson.databind.JavaType ,依次指定主体类class,和多个泛型类class

ObjectMapper mapper = new ObjectMapper();
// 反序列化的时候如果多了其他属性,不抛出异常
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 如果是空对象的时候,不抛异常
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

// 依次指定主体class,n个泛型class
JavaType javaType = mapper.getTypeFactory().constructParametricType(ApiResult.class, DemoVo.class);
ApiResult<DemoVo> api = mapper.readValue(json, javaType);
  1. gson
    gson处理也是类似的,需要定义一个 com.google.gson.reflect.TypeToken 并且在反序列化时使用它:
Type type = new TypeToken<ApiResult<DemoVo>>() {}.getType();
Gson gson = new GsonBuilder().create();
ApiResult<DemoVo> api = gson.fromJson(json, type);

嗯!整体来看,他们在处理泛型时都是大同小异的,在项目中选择合适的框架使用就可以。

转载请注明出处或者链接地址:https://www.qianduange.cn//article/12568.html
标签
评论
发布的文章

jQuery基本使用

2024-06-24 02:06:16

大家推荐的文章
会员中心 联系我 留言建议 回顶部
复制成功!