惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

V
Visual Studio Blog
Y
Y Combinator Blog
奇客Solidot–传递最新科技情报
奇客Solidot–传递最新科技情报
Hugging Face - Blog
Hugging Face - Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
The Cloudflare Blog
L
LangChain Blog
美团技术团队
N
Netflix TechBlog - Medium
量子位
酷 壳 – CoolShell
酷 壳 – CoolShell
B
Blog
博客园 - 司徒正美
爱范儿
爱范儿
D
DataBreaches.Net
月光博客
月光博客
U
Unit 42
B
Blog RSS Feed
Engineering at Meta
Engineering at Meta
Apple Machine Learning Research
Apple Machine Learning Research
Jina AI
Jina AI
MongoDB | Blog
MongoDB | Blog
腾讯CDC

博客园 - 我爱我家喵喵

LookImage2:用 Rust 打造的轻量级专业图像查看器 bat以隐藏模式运行jar包 完美单机155端gs修改:允许10次转生 [Docker] 部署 Nexus Repository OSS 仓库 [docker] 部署 AnythingLLM [nginx] 使用nginx代理实现Ollama支持本地html访问 [docker] 部署 Seata 分布式事务 [docker] 部署 Nacos 服务 CEF 谷歌内核下载地址 [Delphi] 自带皮肤动态切换 [VUE] WebPack 打包后自动修改 dist 中 package.json 版本号 【算法】python版A-Star(A星)寻路 【算法】决策树算法:ID3 【算法】K-means 算法学习 【Unity】使用VSCode调试 [Python] 基于 flask 构建 Web API 实现参数注入和校验 [Redis] 解决多个 Redis 服务同步删除有关联的 key [C#] JavaScript 引擎 [MySql] 数据库死锁的排查和相关知识 [redis] 设置密码
[Java] 扩展 Jackson 的 TypeReference 支持泛型参数传递
我爱我家喵喵 · 2023-03-16 · via 博客园 - 我爱我家喵喵

使用 Jackson 进行复杂类型的反序列化时,可以通过 com.fasterxml.jackson.core.type.TypeReference 来实现,例如:


class User {
  String name;
  Integer age;
}

class Response<T>{
  Integer code;
  T data;
  String msg;
}

public static <T> T toObject(String data, TypeReference<T> clsType) throws JsonProcessingException {
    if (data == null || data.isEmpty()) return null;
    val mapper = new ObjectMapper();
    mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
    return mapper.readValue(data, clsType);
}

public static String toJsonString(Object data) {
      val mapper = new ObjectMapper();
      mapper.configure(SerializationFeature.WRITE_DATE_KEYS_AS_TIMESTAMPS, false);
      try {
          return mapper.writeValueAsString(data);
      } catch (JsonProcessingException e) {
          return data.toString();
      }
}

// 将对象转为json字符串
String data = toJsonString(new Response(0, new User("小明", 18), "OK"));
// 将 json 字符串还原为 Response<User> 对象
Response<User> obj = toObject(data, new TypeReference<Response<User>>(){})

上面的方式看似一切OK,但没办法实现这样的情况:

public static <T> Response<T> toObject(Class<T> cls, String data) throws JsonProcessingException {
    return toObject(data, new TypeReference<Response<T>>(){});
}
// 这样是不行的,泛型 T 的类型没办法传递
Response<User> obj = toObject(User.class, data);

改造 TypeReference, 增加一个带参数的 TypeReference 方法:

import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;

/**
 * @author yangyxd
 */
public class TypeReference<T> extends com.fasterxml.jackson.core.type.TypeReference<T>
{
    protected final Type type;

    // 带参数的方法,支持泛型类传递
    protected <E> TypeReference(Class<E> cls) {
        Type type = ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
        ParameterizedTypeImpl clsInfo = ParameterizedTypeImpl.make(((ParameterizedTypeImpl) type).getRawType(), new Type[]{cls}, null);
        this.type = clsInfo;
    }

    protected TypeReference()
    {
        Type superClass = getClass().getGenericSuperclass();
        if (superClass instanceof Class<?>) { // sanity check, should never happen
            throw new IllegalArgumentException("Internal error: TypeReference constructed without actual type information");
        }
        this.type = ((ParameterizedType) superClass).getActualTypeArguments()[0];
    }

    @Override
    public Type getType() { return type; }
}

这里主要是使用 ParameterizedTypeImpl.make 实现自定义的 ParameterizedTypeImpl,实现想要的功能。

这样可以使用这个带参数的方法:

public static <T> Response<T> toObject(Class<T> cls, String data) throws JsonProcessingException {
    return toObject(data, new TypeReference<Response<T>>(cls){});
}

END