jackson反序列化复杂数据类型(泛型数据类型)

问题

网上很多都是普通的实体类序列化跟反序列化,而对泛型数据的反序列化却比较少,查询了很多资料都不能用,要么就是讲的太复杂,最近在工作中遇到了这个问题,记录下解决方式

资料

首先我们来参考下网上的一段代码,从这段代码中我们可以参看下集合中序列化的方式,但是没有很好的封装,如果写在实际的业务代码中会显得很繁琐,本篇文章我们是借鉴的第一种方式来解决这个问题的


public class Demo{

    public String method() throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        User user = new User();
        user.setId(1);
        Pager<User> pager = new Pager<User>();
        List<User> users = new ArrayList<User>();
        users.add(user);
        pager.setDatas(users);
        String json = mapper.writeValueAsString(pager);
        // 方式1
        Pager<User> userPager1 = mapper.readValue(json, new TypeReference<Pager<User>>() {
        });
        // 方式2
        Type[] types = new Type[1];
        types[0] = User.class;
        final ParameterizedTypeImpl type = ParameterizedTypeImpl.make(Pager.class, types, Pager.class.getDeclaringClass());
        TypeReference typeReference = new TypeReference<Pager>() {
            @Override
            public Type getType() {
                return type;
            }
        };
        Pager<User> userPager2 = mapper.readValue(json, typeReference);
        // 方式3
        JavaType javaType = mapper.getTypeFactory().constructParametrizedType(Pager.class, Pager.class, User.class);
        Pager<User> userPager3 = mapper.readValue(json, javaType);
        // 方式4
        JavaType javaType1 = mapper.getTypeFactory().constructParametricType(Pager.class, User.class);
        Pager<User> userPager4 = mapper.readValue(json, javaType1);
        // 方式5,新建另一个指定具体泛型T的参数的类
        PagerAppoint userPager5 = mapper.readValue(json, PagerAppoint.class);
        // 数组泛型的序列化和反序列化
        String json1 = mapper.writeValueAsString(users);
        JavaType javaType2 = mapper.getTypeFactory().constructParametricType(List.class, User.class);
        List<User> users1 = mapper.readValue(json1, javaType2);
        // HashMap
        Map<String, User> map = new HashMap<String, User>(16);
        map.put("test", user);
        String json2 = mapper.writeValueAsString(map);
        // 1
        Map<String, User> users2 = mapper.readValue(json2, new TypeReference<Map<String, User>>() {
        });
        // 2
        JavaType javaType3 = mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, User.class);
        Map<String, User> users3 = mapper.readValue(json2, javaType3);

        return "hello world";
    }
}

实体类

创建一个包含泛型的实体类,其中data是一个泛型数据

@Data
public class BaseResponse<T> {
    /**
     * 请求ID
     */
    private String requestId;
    /**
     * Token验证码
     */
    private String queueMsg;
    /**
     * 错误编码
     */
    private String errorCode;

    /**
     * 数据
     */
    private T data;

}

再创建一个data对应的实体类

@Data
public class QuerySubmitErrorInfoResponse {
    /**
     * 机构名称
     */
    private String orgname;
    /**
     * 支付服务类别
     */
    private String bizcatgname;
    /**
     * 业务类型
     */
    private String biztypename;
    /**
     * 维度名
     */
    private String dimname;
    /**
     * 第二维度名
     */
    private String dimnames;
    /**
     * 校验信息
     */
    private String remark;

    
}

如果此时T data是一个普通的数据对象,比如QuerySubmitErrorInfoResponse这种,此时很好操作,加入是一个List<QuerySubmitErrorInfoResponse> 此时操作变的繁琐

解决

上面所说的,我用的是第一种思路来解决这个问题,需要一个TypeReference来转换,我简单的封装了一下

public <T> T jsonToObject(String responseJson, TypeReference<T> valueTypeRef) {
        try {
            return mapper.readValue(responseJson, valueTypeRef);
        } catch (IOException e) {
            throw new JsonUtilException("Failed to convert json to object", e);
        }
    }

结束

反序列化代码块如下

BaseResponse<List<QuerySubmitErrorInfoResponse >> response = JsonUtil.create().jsonToObject(result, new TypeReference<BaseResponse<List<QuerySubmitErrorInfoResponse >>>() {
            });

上传一个我用到的完整的工具类

package net.easipay.util.json;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.ser.FilterProvider;

import java.io.IOException;
import java.text.SimpleDateFormat;

public class JsonUtil {

    private ObjectMapper mapper = new ObjectMapper();

    JsonUtil() {
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        //mapper.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
        mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd hh:mm:ss"));
        mapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {
            @Override
            public void serialize(Object paramT, JsonGenerator paramJsonGenerator,
                                  SerializerProvider paramSerializerProvider) throws IOException {
                //设置返回null转为 空字符串""
                paramJsonGenerator.writeString("");
            }
        });
    }

    public static JsonUtil create() {
        return new JsonUtil();
    }


    public JsonUtil setDateFormat(String pattern) {
        mapper.setDateFormat(new SimpleDateFormat(pattern));
        return this;
    }

    public JsonUtil unwrapRootValue() {
        mapper.enable(DeserializationFeature.UNWRAP_ROOT_VALUE);
        return this;
    }

    public JsonUtil wrapRootValue() {
        mapper.enable(SerializationFeature.WRAP_ROOT_VALUE);
        return this;
    }

    public JsonUtil setFilterProvider(FilterProvider filterProvider) {
        mapper.setFilterProvider(filterProvider);
        return this;
    }

    public JsonUtil configure(DeserializationFeature feature, boolean state) {
        mapper.configure(feature, state);
        return this;
    }

    public JsonUtil setPropertyNamingStrategy(PropertyNamingStrategy propertyNamingStrategy) {
        mapper.setPropertyNamingStrategy(propertyNamingStrategy);
        return this;
    }

    public String objectToJson(Object obj) {
        try {
            return mapper.writeValueAsString(obj);
        } catch (JsonProcessingException e) {
            throw new JsonUtilException("Failed to convert object to json", e);
        }
    }

    public <T> T jsonToObject(String responseJson, Class<T> clazz) {
        try {
            return mapper.readValue(responseJson, clazz);
        } catch (IOException e) {
            throw new JsonUtilException("Failed to convert json to object", e);
        }
    }

    public <T> T jsonToObject(String responseJson, TypeReference<T> valueTypeRef) {
        try {
            return mapper.readValue(responseJson, valueTypeRef);
        } catch (IOException e) {
            throw new JsonUtilException("Failed to convert json to object", e);
        }
    }

    public JsonNode getJsonNode(String jsonStr) {
        try {
            return mapper.readTree(jsonStr);
        } catch (JsonProcessingException e) {
            throw new JsonUtilException("Failed to convert request to JsonNode",
                                        e);
        } catch (IOException e) {
            throw new JsonUtilException("IO exception", e);
        }
    }

}

至此,完美解决!

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值