fastjson官方文档_弃坑Fastjson ,进军Jackson

本文介绍了Jackson作为Fastjson替代品的原因,强调了Jackson的高性能、易用性和灵活性。通过示例展示了Jackson的流式API、树模型和数据绑定等特性,并通过ObjectMapper演示了Bean到Json和Json到Bean的转换。最后,提出了优化使用的建议,包括创建全局唯一的ObjectMapper和封装自定义的Jackson工具。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

562b8e9790593255c87bc689434e8336.png

点击上方「Java有货」关注我们

9b28af30d45e7dc5d6ceff0875d72565.gif a12dd5a297849024a854992787529058.png

导      语

656262105db46a51d74d069b397216c5.png

Fastjson 是阿里开源的Json类库,功能很强大,使用也很简单,不得不说温少还是很厉害的,但是fastjson却经常会暴露出高危的漏洞,每次都是紧急发版,导致项目上经常会去更新,这一点让使用者有点痛苦!

json的类库还是很多的,比如:Gosn,JSON-B,Jackson,这三种json类库也是Springboot官方推荐:如下图

1cdae2843514bfd59e45af372dabf6b1.png但是这三者的使用,却没有Fastjson那么方便,接下就进入我们今天的主角:Jackson

9cd0c20a97c65aed875b11f9b2abfe29.png

一. 简介

5933843a0d2c753bacc67bd13007a7c1.gif

Jackson是一个简单基于Java应用库,Jackson可以轻松的将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象。Jackson所依赖的jar包较少,简单易用并且性能也要相对高些,并且Jackson社区相对比较活跃,更新速度也比较快。

1.1 特点
  • 容易使用 - jackson API提供了一个高层次外观,以简化常用的用例。

  • 无需创建映射 - API提供了默认的映射大部分对象序列化。

  • 性能高 - 快速,低内存占用,适合大型对象图表或系统。

  • 干净的JSON - jackson创建一个干净和紧凑的JSON结果,这是让人很容易阅读。

  • 不依赖 - 库不需要任何其他的库,除了JDK。

  • 开源代码 - jackson是开源的,可以免费使用。

1.2 三种方式处理JSON

提供了三种不同的方法来处理JSON

  • 流式API - 读取并将JSON内容写入作为离散事件。JsonParser读取数据,而JsonGenerator写入数据。它是三者中最有效的方法,是最低的开销和最快的读/写操作。它类似于Stax解析器XML。

  • 树模型 - 准备JSON文件在内存里以树形式表示。ObjectMapper构建JsonNode节点树。这是最灵活的方法。它类似于XML的DOM解析器。

  • 数据绑定 - 转换JSON并从POJO(普通Java对象)使用属性访问或使用注释。它有两个类型。

  • 简单的数据绑定 - 转换JSON和Java Maps, Lists, Strings, Numbers, Booleans 和null 对象。

  • 全部数据绑定 - 转换为JSON从任何JAVA类型。

ObjectMapper读/写JSON两种类型的数据绑定。数据绑定是最方便的方式是类似XML的JAXB解析器。

9cd0c20a97c65aed875b11f9b2abfe29.png

二. 初识Jackson

5933843a0d2c753bacc67bd13007a7c1.gif

ObjectMapper类是Jackson库的主要类。它提供一些功能将转换成Java对象匹配JSON结构,反之亦然。它使用JsonParser和JsonGenerator的实例实现JSON实际的读/写

2.1 第一个Jackson程序

本案例以Springboot项目为例,Spring boot已经自带了Jackson依赖,无需额外引用,接下类我们实现两个常用的场景:Bean To Json , Json To Bean

  • Bean To Json

    @Testpublic void beanToJson() throws JsonProcessingException {//创建mapper
ObjectMapper mapper = new ObjectMapper();
User user = new User("123", "123",13);//bean to json
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(user));}

6373f6af53820041b6da12dcd055d20b.png

  • Json To Bean

    @Testpublic void jsonToBean() throws JsonProcessingException {//创建mapper
ObjectMapper mapper = new ObjectMapper();
String jsonString = "{\"name\":\"haiji\", \"age\":21}";// json to bean
System.out.println(mapper.readValue(jsonString, User.class));}

9178380fe9601501cfb03501e2837d10.png

9cd0c20a97c65aed875b11f9b2abfe29.png

三. 进阶Jackson使用

5933843a0d2c753bacc67bd13007a7c1.gif

在上面的案例中我们引进发现,每次使用时都需要创建一个ObjectMapper,而且使用起来也很多的冗余代码,这样我们仅需要进一步优化,如下步骤:

  • 提供全局唯一的ObjectMapper

  • 封装自定义的Jackson 工具

3.1 提供全局唯一的ObjectMapper
@Configurationpublic class JacksonConfig {private final static Logger logger = LoggerFactory.getLogger(JacksonConfig.class);private static ObjectMapper objectMapper;private static Lock LOCK = new ReentrantLock(true);private static AtomicInteger TIME= new AtomicInteger(60);private final static Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();@Bean@Primary@ConditionalOnMissingBean(ObjectMapper.class)public static ObjectMapper jacksonObjectMapper() {if(ObjectUtils.isEmpty(objectMapper)){try {if(LOCK.tryLock(TIME.get(), TimeUnit.SECONDS) && ObjectUtils.isEmpty(objectMapper)){
objectMapper= builder.createXmlMapper(false).build();// 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化// Include.Include.ALWAYS 默认// Include.NON_DEFAULT 属性为默认值不序列化// Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量// Include.NON_NULL 属性为NULL 不序列化
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 允许出现特殊字符和转义符
objectMapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true);// 允许出现单引号
objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);// 字段保留,将null值转为""
objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>(){@Overridepublic void serialize(Object o, JsonGenerator jsonGenerator,
SerializerProvider serializerProvider)throws IOException{
jsonGenerator.writeString("");}});}} catch (InterruptedException e) {
logger.error("object mapper try lock ",e);}finally {
LOCK.unlock();}}return objectMapper;}}
3.2 封装自定义的Jackson 工具
public class JsonUtils<T>{private static Logger logger = LoggerFactory.getLogger(JsonUtils.class);public static <T> T jsonToBean(@Nullable String string, Class<T> bean){assertNotNull("json to bean ", string);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(string, bean);} catch (JsonProcessingException e) {
logger.info("json to object is error -> JsonProcessingException ",e);}return t;}public static <T> String beanToJson(@Nullable T bean){assertNotNull("bean to json ",bean);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
String t = null;try {
t = objectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(bean);} catch (JsonProcessingException e) {
logger.info("json to object is error -> JsonProcessingException ",e);}return t;}public static <T> T jsonToBean(@Nullable String json, TypeReference<T> typeReference){assertNotNull("to json generics",json);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(json, typeReference);} catch (IOException e) {
logger.error("json to object is exception -> ",e);}return t;}public static <T> void beanToJson(@Nullable File file, T bean){assertNotNull("to file",file);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();try {
objectMapper.writeValue(file,bean);} catch (IOException e) {
logger.info("json to object is error -> IOException ",e);}}public static <T> T jsonToBean(@Nullable File file, TypeReference<T> typeReference){assertNotNull("to file",file);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(file,typeReference);} catch (IOException e) {
logger.error("json to object exception -> ",e);}return t;}public static <T> JsonNode jsonToTree(@Nullable String json){assertNotNull("to tree",json);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
JsonNode jsonNode =null;try {
jsonNode = objectMapper.readTree(json);} catch (JsonProcessingException e) {
logger.error("json to tree exception ->",e);}return jsonNode;}public static <T> T jsonToBean(@Nullable URL url, Class<T> bean){assertNotNull("url",url);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(url, bean);} catch (IOException e) {
logger.info("url to object is error -> IOException ",e);}return t;}public static <T> T jsonToBean(@Nullable URL url, TypeReference<T> bean){assertNotNull("url generic paradigm",url);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(url, bean);} catch (IOException e) {
logger.info("url to object is error -> IOException ",e);}return t;}public static <T> T inputStreamToBean(@Nullable InputStream inputStream, Class<T> bean){assertNotNull("inputStream class",inputStream);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(inputStream, bean);} catch (IOException e) {
logger.info("url to object is error -> IOException ",e);}return t;}public static <T> T inputStreamToBean(@Nullable InputStream inputStream, TypeReference<T> bean){assertNotNull("inputStream",inputStream);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(inputStream, bean);} catch (IOException e) {
logger.info("url to object is error -> IOException ",e);}return t;}public static <T> T byteToBean(@Nullable byte[] src, Class<T> bean){assertNotNull("byte class",src);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(src, bean);} catch (IOException e) {
logger.info("url to object is error -> IOException ",e);}return t;}public static <T> T byteToBean(@Nullable byte[] src, TypeReference<T> bean){assertNotNull("byte TypeReference",src);
ObjectMapper objectMapper = JacksonConfig.jacksonObjectMapper();
T t = null;try {
t = objectMapper.readValue(src, bean);} catch (IOException e) {
logger.info("url to object is error -> IOException ",e);}return t;}protected static void assertNotNull(String paramName, Object src) {if (ObjectUtils.isEmpty(src)) {throw new IllegalArgumentException(String.format("argument \"%s\" is null", paramName));}}}
3.3 使用验证
    @Testpublic void testJson(){
User user = new User("123", "123",13);
System.out.println(JsonUtils.beanToJson(user));
String jsonString = "[{\"name\":\"haiji\", \"age\":21},{\"name\":\"java\", \"age\":21}]";
System.out.println(JsonUtils.jsonToBean(jsonString, new TypeReference<List<User>>() {}));}

7d3b105abfcff65a267fd2b1b0b1e9f2.png这里只是对常用的一些json工具进行了封装,大家也可以自己进行

案例源代码地址:https://github.com/yanghaiji/javayh-platform/tree/master/javayh-dependencies/javayh-common-starter/src/main/java/com/javayh/common

如果对你有帮助,请给个赞吧!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值