java解析json jackson gson fastjson json-lib

java解析json 常用的类库有 jackson gson FastJson Json-lib

综合来讲 Jackson性能较好

Gosn 功能最全

fastjson速度较快 但安全漏洞较多

json-lib

(1) jackson使用

jackson

<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-core</artifactId>
    <version>2.11.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-databind</artifactId>
    <version>2.11.0</version>
</dependency>
<dependency>
    <groupId>com.fasterxml.jackson.core</groupId>
    <artifactId>jackson-annotations</artifactId>
    <version>2.11.0</version>
</dependency>

(1.1) 对象转字符串


   /**
    * 对象转字符串
    */
   @Test
   public void writeObjectAsString() {

	ObjectMapper objectMapper = new ObjectMapper();

       UserVo user = getUserVo();

       String json = null;
       try {
           json = objectMapper.writeValueAsString(user);
       } catch (JsonProcessingException e) {
           log.error("", e);
	}
	
	// {"id":2305843116587876352,"name":"李四","age":20,"birthday":1591402080000,"email":"lisi@gmail.com","address":["北京","天津"],"arr":["A","b"]}
       log.info("json:{}", json);

}
/**
 * @return
 */
public UserVo getUserVo() {
    UserVo user = new UserVo();
    Long x = 100L + Integer.MAX_VALUE + 1 << 30;
    log.info("id:{}", x);
    user.setId(x);
    user.setName("李四");
    user.setEmail("lisi@gmail.com");
    user.setAge(20);
    try {
        SimpleDateFormat dateformat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date date = dateformat.parse("2020-06-06 08:08:00");
        user.setBirthday(date);
    } catch (ParseException e) {
        log.error("", e);
    }
    List<String> list = Arrays.asList("北京", "天津");
    user.setAddress(list);
    String[] arr = {"A", "b"};
    user.setArr(arr);
    return user;
}
class UserVo {
    private Long id;
    private String name;
    private Integer age;
    private Date birthday;
    private String email;
    private List<String> address;
    private String[] arr;

	// 省略 getter setter
}

(1.2) 字符串转对象

   /**
    * 字符串转对象
    */
   @Test
   public void readStringAsObject() {
       String json = "{\"id\":2305843116587876352,\"name\":\"李四\",\"age\":20,\"birthday\":1591402080000,\"email\":\"lisi@gmail.com\",\"address\":[\"北京\",\"天津\"],\"arr\":[\"A\",\"b\"]}\n";

	ObjectMapper objectMapper = new ObjectMapper();

	UserVo userVo = null;
       try {
           userVo = objectMapper.readValue(json, UserVo.class);
       } catch (JsonProcessingException e) {
           log.error("", e);
       } catch (IOException e) {
           log.error("", e);
       }

   	log.info("{}  {}  {}  {}  {}  {} {} ", userVo.getId(), userVo.getAddress(), userVo.getAge(), userVo.getArr(), userVo.getBirthday(), userVo.getEmail(), userVo.getName());
   
}

(1.3) 集合转字符串

  /**
   * 集合转字符串
   */
  @Test
  public void writeListAsString() {

      List<UserVo> list = getUserList();

      String json = null;
      try {
          json = objectMapper.writeValueAsString(list);
      } catch (JsonProcessingException e) {
          log.error("", e);
}

// [{"id":1,"name":"李四","age":null,"birthday":null,"email":null,"address":["北京","天津"],"arr":["A","b"]},{"id":2,"name":"张三","age":null,"birthday":null,"email":null,"address":["河北","山东"],"arr":["C","中文"]}]
      log.info("json:{}", json);

  }
/**
    * @return
    */
   public List<UserVo> getUserList() {

       List<UserVo> list = new ArrayList(2);

       UserVo user = new UserVo();
       user.setId(1L);
       user.setName("李四");
       List<String> addrs = Arrays.asList("北京", "天津");
       user.setAddress(addrs);
       String[] arr = {"A", "b"};
       user.setArr(arr);

       UserVo user2 = new UserVo();
       user2.setId(2L);
       user2.setName("张三");
       List<String> addrs2 = Arrays.asList("河北", "山东");
       user2.setAddress(addrs2);
       String[] arr2 = {"C", "中文"};
       user2.setArr(arr2);

       list.add(user);
       list.add(user2);

       return list;
   }

(2.4) 字符串转集合

/**
 * 字符串转集合
 */
@Test
public void readStringAsList() {
    String json = "[{\"id\":1,\"name\":\"李四\",\"age\":null,\"birthday\":null,\"email\":null,\"address\":[\"北京\",\"天津\"],\"arr\":[\"A\",\"b\"]},{\"id\":2,\"name\":\"张三\",\"age\":null,\"birthday\":null,\"email\":null,\"address\":[\"河北\",\"山东\"],\"arr\":[\"C\",\"中文\"]}]";

    JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, UserVo.class);
    //如果是Map类型  mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, Bean.class);
    List<UserVo> list = null;
    try {
        list = objectMapper.readValue(json, javaType);
    } catch (JsonProcessingException e) {
        log.error("", e);
    } catch (IOException e) {
        log.error("", e);
    }

    for (UserVo userVo : list) {
    	log.info("{}  {}  {}  {}  {}  {} {} ", userVo.getId(), userVo.getAddress(), userVo.getAge(), userVo.getArr(), userVo.getBirthday(), userVo.getEmail(), userVo.getName());
    }
}
/**
 * 字符串转集合
 */
@Test
public void readStringAsList() {
    String json = "[{\"id\":1,\"name\":\"李四\",\"age\":null,\"birthday\":null,\"email\":null,\"address\":[\"北京\",\"天津\"],\"arr\":[\"A\",\"b\"]},{\"id\":2,\"name\":\"张三\",\"age\":null,\"birthday\":null,\"email\":null,\"address\":[\"河北\",\"山东\"],\"arr\":[\"C\",\"中文\"]}]";

    JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, UserVo.class);
    //如果是Map类型  mapper.getTypeFactory().constructParametricType(HashMap.class, String.class, Bean.class);
    List<UserVo> list = null;
    try {
        list = objectMapper.readValue(json, javaType);
    } catch (JsonProcessingException e) {
        log.error("", e);
    } catch (IOException e) {
        log.error("", e);
    }

    for (UserVo userVo : list) {
    	log.info("{}  {}  {}  {}  {}  {} {} ", userVo.getId(), userVo.getAddress(), userVo.getAge(), userVo.getArr(), userVo.getBirthday(), userVo.getEmail(), userVo.getName());
    }

}

(2) gson

(3) fastjson

使用 fastjson 时遇到的问题

java.lang.VerifyError

java.lang.VerifyError: (class: com/alibaba/fastjson/parser/deserializer/FastjsonASMDeserializer_3_ErpOrderResVo, method: deserialze signature: (Lcom/alibaba/fastjson/parser/DefaultJSONParser;Ljava/lang/reflect/Type;Ljava/lang/Object;I)Ljava/lang/Object;) Accessing value from uninitialized register 85
	at java.lang.Class.getDeclaredConstructors0(Native Method)

fastjson 32个字段时反序列化报错的问题

1.2.28 32整数倍个字段 OOM bug
32个字段时反序列化报错

(3) 老办法

以下是老方法/笨办法


import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.xxxx.file.FileUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;

/**
 * @version V1.0
 * @date 2017-09-21 21:48
 */
public class JsonTest {
    
    private static final Logger logger = LoggerFactory.getLogger(JsonTest.class);
    
	public static void main(String[] args) {

	    String str = null;
        String filePath = "doc/html/xiecheng/crawler_flights_bj-yc-2017-09-23_result.json";
        try {
            str = FileUtil.readFile2String(filePath);
        } catch (IOException e) {
            logger.error("", e);
        }
        
        JSONObject json = JSONObject.parseObject(str);
        JSONArray fisArray = json.getJSONArray("fis");
        
        int size = fisArray.size();
        for(int i = 0; i < size; i++){
            JSONObject oneFlight = (JSONObject) fisArray.get(i);
            logger.info(i +": {}", oneFlight);
        }
        
    }
	
	
	/**
	 *
	 * @param str
	 */
	public List<Map<String, String>> parserJson(String str) {

		if (StringUtil.isEmpty(str)) {
			logger.error("json为空");
			return null;
		}

		JSONObject json = JSONObject.parseObject(str);

		// 航空公司
		JSONObject als = (JSONObject) json.get("als");
		logger.info("符合要求的航空公司:{}", als);
		Set<Map.Entry<String, Object>> set = als.entrySet();
		logger.info("set:{}", set);

		JSONObject apb = (JSONObject) json.get("apb");
		logger.info("符合要求的机场:{}", apb);

		// 中转组合,暂时不考虑,业务上也暂时不需要,稍微有点复杂,时间允许可以解析
		// json.get("tf");

		// 直航
		JSONArray fisArray = json.getJSONArray("fis");
		if (fisArray == null || fisArray.isEmpty()) {
			logger.error("fisArray结果为空");
			return null;
		}

		int size = fisArray.size();
		if (size == 0) {
			logger.error("fisArray 里元素个数为0");
			return null;
		}

		List<Map<String, String>> list = new ArrayList<>(size);

		for (int i = 0; i < size; i++) {

			Map<String, String> dataMap = new HashMap<>(16);

			//
			JSONObject oneFlight = (JSONObject) fisArray.get(i);
			logger.debug(i + ": {}", oneFlight);

			// 到达城市代码
			String acc = (String) oneFlight.get("acc");
			dataMap.put("acc", acc);

			// 目的地
			String acn = (String) oneFlight.get("acn");
			dataMap.put("acn", acn);

			// 航空公司
			String alc = (String) oneFlight.get("alc");
			String flightCompany = null;
			if (als.containsKey(alc)) {
				flightCompany = als.getString(alc);
			}
			dataMap.put("alc", flightCompany);

			// 到达机场
			String apbn = (String) oneFlight.get("apbn");
			dataMap.put("apbn", apbn);

			// 到达时间
			String at = (String) oneFlight.get("at");
			dataMap.put("at", at);

			// 到达城市代码
			String dcc = (String) oneFlight.get("dcc");
			dataMap.put("dcc", dcc);

			// 出发地
			String dcn = (String) oneFlight.get("dcn");
			dataMap.put("dcn", dcn);

			// 出发机场
			String dpbn = (String) oneFlight.get("dpbn");
			dataMap.put("dpbn", dpbn);

			// 航站楼
			String dsmsn = (String) oneFlight.get("dsmsn");
			dataMap.put("dsmsn", dsmsn);

			// 出发时间
			String dt = (String) oneFlight.get("dt");
			dataMap.put("dt", dt);

			// 航班号
			String fn = (String) oneFlight.get("fn");
			dataMap.put("fn", fn);

			// 实际票价
			String lp = oneFlight.get("lp").toString();
			dataMap.put("lp", lp);

			JSONObject confort = oneFlight.getJSONObject("confort");
			String historyPunctualityArr = (String) confort.get("HistoryPunctualityArr");
			if (StringUtil.isNotEmpty(historyPunctualityArr)) {
				dataMap.put("historyPunctualityArr", historyPunctualityArr.replace("%", ""));
			}

			logger.info("本条航班数据:{}", dataMap);

			list.add(dataMap);
		}

		return list;

	} // end method
	
    
}

References

[1] Java几种常用JSON库性能比较
[2] jackson-docs
[3] jackson-object-mapper-tutorial