放棄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

歡迎關注我的公衆號,【大數據技術與應用實戰】,獲取更多精彩內容
在這裏插入圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章