放弃fastjson,拥抱Jackson

背景

最近由于阿里的fastjson频繁爆出安全漏洞,为了避免后续升级上线的烦恼,决定弃用fastjson,使用Jackson,把现有项目中的fastjson都换成了Jackson,由于很多写法上有些不同,所以在这里把这些改过的东西做一下笔记。

常用操作

首先引入相关的pom


    <properties>
        <jackson.version>2.11.0</jackson.version>
    </properties>
    <dependencies>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-core</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>${jackson.version}</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-annotations</artifactId>
            <version>${jackson.version}</version>
        </dependency>
    </dependencies>

在这里插入图片描述

json object操作

当我们需要一个json对象和json数组的时候,我们可以使用下面的方法来构造ObjectNode和ArrayNode,类似fastjson中的JSONObject和JSONArray。


	@Test
	public void testJsonObject(){
		ObjectMapper mapper = new ObjectMapper();
		ObjectNode json = mapper.createObjectNode();
		json.put("name", "Tom");
		json.put("age", 1);
		System.out.println(json);

		ArrayNode jsonNodes = mapper.createArrayNode();
		jsonNodes.add(json);
		System.out.println(jsonNodes);
	}

序列化操作

序列化操作就是将Java对象转化成json,简单的语法如下:


	@Test
	public void testSerialize() throws JsonProcessingException{
		User user = new User();
		user.setAge(1);
		user.setName("zhangsan");
		user.setGender(GENDER.MALE);
		user.setBirthday(new Date());
		ObjectMapper mapper = new ObjectMapper();
		String s = mapper.writeValueAsString(user);
		System.out.println(s);
	}


普通的String和int类型没有什么疑问,我们这里涉及了两个特殊类型,一个是Date,还有一个是枚举。
日期类型我们是通过注解@JsonFormat对日期类型做了格式化,可以控制输出的日期格式。


@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd HH:mm:ss")
private Date birthday;

枚举类型,我们通过注解@JsonValue来控制输出哪个字段。


     	@JsonValue
		public String getName(){
			return name;
		}

反序列化

反序列化就是将json转化成Java对象,语法如下:


	@Test
	public void testDeSerialize() throws JsonProcessingException{
		String json = "{\"name\":\"zhangsan\",\"age\":10}";
		ObjectMapper mapper = new ObjectMapper();
		User user = mapper.readValue(json, User.class);
		System.out.println(user);
	}


日期类型反序列化

对于Date类型,目前支持以下的格式:

  • long类型的时间戳
  • 通过@JsonFormat 注解指定类型格式:yyyy-MM-dd HH:mm:ss

	@Test
	public void testDeSerializeDate() throws JsonProcessingException{
		String json = "{\"name\":\"zhangsan\",\"age\":10,\"birthday\":1592800446397}";
		ObjectMapper mapper = new ObjectMapper();
		User user = mapper.readValue(json, User.class);
		System.out.println(user);

		String json1 = "{\"name\":\"zhangsan\",\"age\":10,\"birthday\":\"2020-01-01 12:13:14\"}";
		User user1 = mapper.readValue(json1, User.class);
		System.out.println(user1);

	}

自定义反序列化

有时候系统提供的反序列化方式不能满足我们的需求,我们可以自定义一些方法来满足我们个性化的需求,我们以一个日期为例,讲讲如何自定义反序列化。

首先我们在对应的字段上通过注解@JsonDeserialize来指定反序列化的类

@JsonDeserialize(using = CustomDeserializerDate.class)
   	private Date birthday_custom;

自定义的序列化类继承抽象类StdDeserializer,此外我们还要添加一个无参构造方法,否则会报错。
在deserialize方法里我们实现反序列化的逻辑.



   public static class CustomDeserializerDate extends StdDeserializer<Date>{

   	private static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

   	protected CustomDeserializerDate(Class<?> vc){
   		super(vc);
   	}

   	//需要一个无参构造方法,否则会报错
   	public CustomDeserializerDate(){
   		this(null);
   	}

   	@Override
   	public Date deserialize(
   			JsonParser p,
   			DeserializationContext ctxt) throws IOException{
   		String date = p.getText();
   		try {
   			return sdf.parse(date);
   		} catch (ParseException e){
   			e.printStackTrace();
   		}
   		return null;
   	}
   }

枚举类型反序列化

最后我们讲一下枚举类型的反序列化

如下代码所示,我们通过注解@JsonCreator来处理枚举反序列化,该方法接收一个int类型的参数,也就是枚举的value值,返回枚举类型GENDER。
如果没找到,则返回null.


	public static enum GENDER{
		MALE("男", 1), FEMALE("女", 0);
		private String name;
		private int value;

		@JsonCreator
		public static GENDER getGenderById(int value){
			for (GENDER c: GENDER.values()){
				if (c.getValue() == value){
					return c;
				}
			}
			return null;
		}
		
		..........
   }

完整代码请参考:
https://github.com/zhangjun0x01/bigdata-examples/blob/master/java/src/main/java/json/JacksonTest.java

欢迎关注我的公众号,【大数据技术与应用实战】,获取更多精彩内容
在这里插入图片描述

### FastJSONJackson 的对比 #### 性能表现 FastJSONJackson 在性能方面表现出色,在 JSON序列化Java 对象的速度上两者非常接近[^2]。尽管存在细微差异,但在大多数实际应用场景中这种差距几乎可以忽略不计。 #### 功能特性 Jackson 是一个广泛使用的基于 JavaJSON 库,不仅能够处理 JSON 和 XML 与 JavaBean 间的相互转换,还提供了高效的解析能力以及较低的内存消耗。相比之下,FastJSON 更加专注于 JSON 处理,并且其 `JSONObject` 实现了 Map 接口,允许像操作标准集合一样访问其中的数据结构;然而 Jackson 默认并不提供这样的便利性,对于特殊需求可能需要额外编码来实现相同的功能[^4]。 #### 生态系统和支持度 作为 Maven 中最受欢迎的选择之一,Jackson 得到了社区的高度认可并被 Spring Boot 设定为其首选默认库。这意味着当开发者采用该框架构建项目时,默认情况下会优先考虑集成 Jackson 来完成数据交换任务。此外,由于 Jackson 提供了丰富的 API 文档和技术支持渠道,使得它成为企业级应用开发中的理想选择[^3]。 #### 使用场景建议 - **Web服务端点**:如果应用程序主要涉及 RESTful Web Service 或者微服务架构下的通信,则推荐选用 Jackson ,因为它是目前最成熟稳定的选择。 - **内部工具或脚本编写**:考虑到 FastJSON 易于使用的特点及其良好的中文文档资源,这可能是快速原型设计或是小型项目的不错选项。 - **高性能要求的应用程序**:虽然两者的性能相差不大,但如果确实有严格的性能指标考量,可以通过基准测试具体评估哪款更适合特定环境。 ```java // 示例代码展示如何利用 Jackson 进行简单的序列化和反序列化操作 import com.fasterxml.jackson.databind.ObjectMapper; public class Example { public static void main(String[] args) throws Exception { ObjectMapper mapper = new ObjectMapper(); String jsonString = "{\"name\":\"John\",\"age\":30}"; User user = mapper.readValue(jsonString, User.class); System.out.println(user.getName()); // 输出 John String serializedUser = mapper.writeValueAsString(user); System.out.println(serializedUser); // {"name":"John","age":30} } } class User { private String name; private int age; // Getters & Setters... } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值