Java 之 JSON 转换(jackson 与 fastJson)

#Jackson

推荐阅读:

前言:相比于 FastJson 和 Gson,Jackson 在性能、运行速度、开源社区的活跃度等方面的综合性能都要更好

一、简介

1、版本介绍

  • Jackson 的 1.x 版本的包名是 org.codehaus.jackson
  • 当升级到 2.x 版本时,包名变为 com.fasterxml.jackson

源码地址:FasterXML/jackson

2、核心模块

Jackson 的核心模块由三部分组成:

  • jackson-core:核心包,提供基于"流模式"解析的相关 API,包括 JsonPaser 和 JsonGenerator

    Jackson 内部实现通过高性能的流模式 API 的 JsonGenerator 和 JsonParser 来生成和解析 json

  • jackson-annotations:注解包,提供标准注解功能
  • jackson-databind:数据绑定包, 提供基于"对象绑定" 解析的相关 API ObjectMapper 和"树模型" 解析的相关 API JsonNode

    基于"对象绑定" 解析的 API 和"树模型"解析的 API 依赖基于"流模式"解析的 API

3、Maven 依赖

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

注:jackson-databind 依赖 jackson-core 和 jackson-annotations

完整 Maven 依赖

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

二、ObjectMapper

Jackson 最常用的 API 就是基于"对象绑定" 的 ObjectMapper:

  • ObjectMapper 可以从字符串、流、文件中解析 JSON,并创建表示已解析的 JSON 的 Java 对象

    将 JSON 解析为 Java 对象也称为从 JSON 反序列化 Java 对象

  • ObjectMapper 也可以从 Java 对象创建 JSON

    从 Java 对象生成 JSON 也称为将 Java 对象序列化为 JSON

  • Object 映射器可以将 JSON 解析为自定义的类对象,也可以解析置JSON树模型的对象

之所以称为ObjectMapper是因为它将JSON映射到Java对象(反序列化),或者将Java对象映射到JSON(序列化)

1、JSON 字符串转 Java 对象

ObjectMapper objectMapper = new ObjectMapper();
//1. JSON 字符串 --> Java 对象
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
Car car = objectMapper.readValue(carJson, Car.class);

//2. JSON 数组字符串 --> Java 对象数组
String carJsonArray = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
Car[] cars2 = objectMapper.readValue(carJsonArray, Car[].class);

//3. JSON 数组字符串 --> List
String carJsonList = "[{\"brand\":\"ford\"}, {\"brand\":\"Fiat\"}]";
List<Car> cars3 = objectMapper.readValue(carJsonList, new TypeReference<List<Car>>() {});

//4. JSON 字符串 --> Map
String carJsonMap = "{\"brand\":\"ford\", \"doors\":5}";
Map<String, Object> jsonMap = objectMapper.readValue(carJsonMap, new TypeReference<Map<String, Object>>() {});

2、Java 对象转 JSON 字符串

  • writeValue()
  • writeValueAsString()
  • writeValueAsBytes()`
ObjectMapper objectMapper = new ObjectMapper();

Car car = new Car();
car.setBrand("BMW");
car.setDoors(4);

//1. Java 对象转 JSON,并写入 FileOutputStream
objectMapper.writeValue(new FileOutputStream("data/output-2.json"), car);
//2. Java 对象转 JSON 字符串
String json = objectMapper.writeValueAsString(car);

3、Jackson 日期转化

ObjectMapper objectMapper = new ObjectMapper();

//1. Date --> long(unix字符串)
String output = objectMapper.writeValueAsString(new Date());
//2. Date --> String
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
objectMapper.setDateFormat(dateFormat);
String output2 = objectMapper.writeValueAsString(new Date());

4、Jackson JSON 树模型

  • Jackson 具有内置的树模型,可用于表示 JSON 对象
  • 若不知道接收到的 JSON 格式,或者由于某种原因而不能创建一个类来表示,则可以用 Jackson 树模型
  • 若需要在使用或转化 JSON 之前对其进行操作,也可以使用 Jackson 树模型

Jackson 树模型由 JsonNode 类表示,可以使用 Jackson ObjectMapper 将 JSON 解析为 JsonNode 树模型,就像使用自定义类一样

ObjectMapper objectMapper = new ObjectMapper();
String carJsonMulti = "{ \"brand\" : \"Mercedes\", " +
					"\"doors\" : 5," +
                	"  \"owners\" : [\"John\", \"Jack\", \"Jill\"]," +
                	"  \"nestedObject\" : { \"field\" : \"value\" } }";
//1. 解析为 JsonNode 对象
JsonNode jsonNode = objectMapper.readValue(carJsonMulti, JsonNode.class); //法一
JsonNode jsonNode2 = objectMapper.readTree(carJsonMulti); //法二

//2. 浏览 JsonNode 树模型
JsonNode brandNode = jsonNode.get("brand");
String brand = brandNode.asText();

JsonNode doorsNode = jsonNode.get("doors");
int doors = doorsNode.asInt();

JsonNode array = jsonNode.get("owners");
String john = array.get(0).asText();

JsonNode child = jsonNode.get("nestedObject");
String field = child.get("field").asText();

//3. Java对象 --> JsonNode
Car car = new Car("Cadillac", 4);
JsonNode carJsonNode = objectMapper.valueToTree(car);

//4. JsonNode --> Java对象
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
JsonNode carJsonNode2 = objectMapper.readTree(carJson);
Car car2 = objectMapper.treeToValue(carJsonNode2, Car.class);

5、配置信息

 //在反序列化时忽略在 json 中存在但 Java 对象不存在的属性
 objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
 //在序列化时日期格式默认为 yyyy-MM-dd'T'HH:mm:ss.SSSZ
 objectMapper.configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS,false)
 //在序列化时忽略值为 null 的属性
 objectMapper.setSerializationInclusion(Include.NON_NULL);
 //忽略值为默认值的属性
 objectMapper.setDefaultPropertyInclusion(Include.NON_DEFAULT);

三、JsonNode

  • Jackson 可以将 JSON 读取到 JsonNode 实例中,然后将 JsonNode 写入 JSON
  • 由于 JsonNode 类不可变,因此不能直接构建 JsonNode 实例,但可以创建 JsonNode 子类 ObjectNode 实例
    作为 JsonNode 的子类,可以在使用 JsonNode 的任何地方使用 ObjectNode
ObjectMapper objectMapper = new ObjectMapper();
 //1. 获取 JsonNode 字段
String jsonValue = "{\"field1\" : \"value1\", \"field2\" : 999}";
JsonNode jsonNode = objectMapper.readTree(jsonValue);
JsonNode field1 = jsonNode.get("field1");
JsonNode field2 = jsonNode.get("field2");

//2. 在路径中获取 JsonNode 字段
String jsonValue2 = "{\"identification\" :  {\"name\" : \"James\",\"ssn: \"ABC123552\"}}";
JsonNode jsonNode2 = objectMapper.readTree(jsonValue2);
JsonNode nameNode = jsonNode2.at("/identification/name");

//3. 转换 JsonNode 字段
//3.1 将 String 字段值转换为 double/int/long
String f2Str = jsonNode.get("f2").asText();
double f2Dbl = jsonNode.get("f2").asDouble();
int f2Int = jsonNode.get("f2").asInt();
long f2Lng = jsonNode.get("f2").asLong();
//3.2 使用默认值转换(若字段值为空,则提供默认值)
String jsonValue3 = "{ \"f1\":\"Hello\", \"f2\":null }";
JsonNode jsonNode3 = objectMapper.readTree(jsonValue3);
String f2Value = jsonNode3.get("f2").asText("Default");
//3.3 若 json 中没有该值,jsonNode.get 返回 null,若此时调用 asText 等方法,将 NullPointerException
String jsonValue4 = "{ \"f1\":\"Hello\" }";
JsonNode jsonNode4 = objectMapper.readTree(jsonValue4);
JsonNode f2FieldNode = jsonNode.get("f2");

//4. 操作 JsonNode 的子类 ObjectNode
//4.1 创建一个 ObjectNode
ObjectNode objectNode = objectMapper.createObjectNode();
//4.2 Set ObjectNode 字段
String jsonValue5 = "{ \"f1\":\"Hello\" }";
JsonNode jsonNode5 = objectMapper.readTree(jsonValue5);
objectNode.set("child1", jsonNode5);
//4.3 Put ObjectNode 字段
objectNode.put("field1", "value1");
objectNode.put("field2", 123);
objectNode.put("field3", 999.999);
//4.4 删除字段
objectNode.remove("field1");

//5. 循环 JsonNode 字段
Iterator<String> fieldNames = objectNode.fieldNames();
while (fieldNames.hasNext()) {
	String fieldName = fieldNames.next();
    JsonNode field = jsonNode.get(fieldName);
}

四、JsonParser

JsonParser 的运行层级低于 ObjectMapper,因此 JsonParser 比 ObjectMapper 更快,但使用也比较麻烦

//1. 创建一个 JsonParser
String carJson = "{ \"brand\" : \"Mercedes\", \"doors\" : 5 }";
JsonFactory factory = new JsonFactory();
JsonParser parser = factory.createParser(carJson);

//2. 用 JsonParser 转化 JSON
while (!parser.isClosed()) {
	JsonToken jsonToken = parser.nextToken();
    System.out.println("jsonToken = " + jsonToken);
}

使用 JsonParser 的 nextToken() 获得一个 JsonToken,可以使用此 JsonToken 实例检查给定的令牌:
START_OBJECT、END_OBJECT、START_ARRAY、END_ARRAY、FIELD_NAME、VALUE_EMBEDDED_OBJECT、VALUE_FALSE、VALUE_TRUE、VALUE_NULL、VALUE_STRING、VALUE_NUMBER_INT、VALUE_NUMBER_FLOAT

五、JsonGenerator

JsonGenerator 用于从 Java 对象(或代码从中生成 JSON 的任何数据结构)生成 JSON

//1. 创建一个 JsonGenerator
JsonFactory factory = new JsonFactory();
//1.1 第一个参数是生成的 JSON 的目标
JsonGenerator generator = factory.createGenerator(new File("data/output.json"), JsonEncoding.UTF8);

//2. 使用JsonGenerator生成JSON
generator.writeStartObject();
generator.writeStringField("brand", "Mercedes");
generator.writeNumberField("doors", 5);
generator.writeEndObject();

//3. 关闭 JsonGenerator
generator.close();

六、Jackson注解

Jackson 注解可以用来设置将 JSON 读入对象的方式或从对象生成什么 JSON 的方式

常用注解:

注解用法
@JsonProperty用于属性,把属性的名称序列化时转换为另外一个名称
@JsonFormat用于属性或者方法,把属性或方法的格式序列化时转换成指定的格式
@JsonPropertyOrder用于类, 指定属性在序列化时 json 中的顺序
@JsonCreator用于构造方法,和 @JsonProperty 配合使用,适用有参数的构造方法
@JsonAnySetter用于属性或者方法,设置未反序列化的属性名和值作为键值存储到 map 中
@JsonAnyGetter用于方法 ,获取所有未序列化的属性

1、Read + Write 注解

读+写注解:会影响从 JSON 读取 Java 对象以及将 Java 对象写入 JSON

  • @JsonIgnore:将 JSON 读取到 Java 对象或将 Java 对象写入 JSON 时,都忽略该属性
    public class PersonIgnore {
    	@JsonIgnore
    	public long  personId = 0;
    }
    
  • @JsonIgnoreProperties:用于类,指定要忽略的类的属性列表
    @JsonIgnoreProperties({"firstName", "lastName"})
    public class PersonIgnoreProperties {
    }
    
  • @JsonIgnoreType:将整个类型(类)标记为在使用该类型的任何地方都将被忽略
    public class PersonIgnoreType {
    
    	@JsonIgnoreType
    	public static class Address {
        	public String streetName  = null;
        	public String houseNumber = null;
        	public String zipCode     = null;
        	public String city        = null;
        	public String country     = null;
    	}
    	public long    personId = 0;
    }
    
  • @JsonAutoDetect:作用在类上,开启/禁止自动检测
    • fieldVisibility:字段的可见级别
    • ANY:任何级别的字段都可以自动识别
    • NONE:所有字段都不可以自动识别
    • NON_PRIVATE:非private修饰的字段可以自动识别
    • PROTECTED_AND_PUBLIC:被protected和public修饰的字段可以被自动识别
    • PUBLIC_ONLY:只有被public修饰的字段才可以被自动识别
    • DEFAULT:同PUBLIC_ONLY

2、Read 注解

读注解:仅影响将JSON 解析为对象的方式,即对JSON的读取

  • @JsonSetter:当将 JSON 读入对象时,应将此 setter 方法的名称与 JSON 数据中的属性名称匹配

    若 Java 类内部使用的属性名称与 JSON 文件中使用的属性名称不同,这个注解就很有用

  • @JsonAnySetter:为 JSON 对象中所有无法识别的字段调用相同的 setter 方法

    “无法识别”:指尚未映射到 Java 对象中的属性或设置方法的所有字段

  • @JsonCreator:该 Java 对象具有一个构造函数,该构造函数可以将 JSON 对象的字段与Java对象的字段进行匹配
  • @JacksonInject:用于将值注入到解析的对象中,而不是从 JSON 中读取这些值
    public class PersonInject {
    	public long   id   = 0;
    	public String name = null;
    
     	@JacksonInject
    	public String source = null;
    }
    

    将值注入 Java 对象:

    InjectableValues inject = new InjectableValues.Std().addValue(String.class, "jenkov.com");
    PersonInject personInject = new ObjectMapper().reader(inject)
                    .forType(PersonInject.class)
                    .readValue(new File("data/person.json"));
    
  • @JsonDeserialize:为 Java 对象中给定的属性指定自定义反序列化器类

3、Write 注解

Write 注解:可以影响 Jackson 将 Java 对象序列化(写入)到 JSON 的方式

  • @JsonInclude:仅在某些情况下包括属性

    例如:仅当属性为非null,非空或具有非默认值时,才应包括该属性

    @JsonInclude(JsonInclude.Include.NON_EMPTY)
    public class PersonInclude {
        public long  personId = 0;
        public String name     = null;
    }
    
  • @JsonGetter:通过调用 getter 方法而不是通过直接字段访问来获取某个字段值
  • @JsonAnyGetter:可以将 Map 用作要序列化为 JSON 的属性的容器
  • @JsonPropertyOrder:用于指定将 Java 对象的字段序列化为 JSON 的顺序
    @JsonPropertyOrder({"name", "personId"})
    public class PersonPropertyOrder {
        public long  personId  = 0;
        public String name     = null;
    }
    
  • @JsonRawValue:表示该属性值应直接写入 JSON输 出
  • @JsonValue:不应该尝试序列化对象本身,而应在对象上调用将对象序列化为JSON字符串的方法
  • @JsonSerialize:用于为 Java 对象中的字段指定自定义序列化程序

# fastJson

1、json 字符串转 JSONObject

  • JSON.parseObject() 方法将 Json 字符串转化为 JSON 对象
  • JSONObject.get() 方法来获取 JSONObject 中的相对应的键对应的值
public void JsonStrToJSONObject(){
    String  JSON_OBJ_STR = "{\"studentName\":\"lily\",\"studentAge\":12}";
    JSONObject jsonObject = JSON.parseObject(JSON_OBJ_STR);
    System.out.println("StudentName: " + jsonObject.getString("studentName") + "," + "StudentAge: " + jsonObject.getInteger("studentAge"));
}

2、JSONObject 转 json字符串

public void JSONObjectToJSONString(){
	//json字符串-简单对象型,加\转义
    String  JSON_OBJ_STR = "{\"studentName\":\"lily\",\"studentAge\":12}";
	JSONObject jsonObject = JSON.parseObject(JSON_OBJ_STR);
    String s = JSON.toJSONString(jsonObject);
    System.out.println(s);
}

3、JSON字符串数组转 JSONArray

  • 方式一:通过 jsonArray.size() 获取 JSONArray 元素个数,再通过 getJSONObject(index) 获取相应位置的 JSONObject,循环变量取得 JSONArray 中的 JSONObject,再利用 JSONObject.get() 进行取值
  • 方式二:通过 jsonArray.iterator() 获取迭代器
public void JSONArrayToJSONStr(){
	//json字符串-数组类型
    String  JSON_ARRAY_STR = "[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]";
	JSONArray jsonArray = JSON.parseArray(JSON_ARRAY_STR);
	//方式一
	int size = jsonArray.size();
	for(int i = 0;i < size;i++){
		JSONObject jsonObject1 = jsonArray.getJSONObject(i);
		 System.out.println("studentName: " + jsonObject1.getString("studentName") + ",StudentAge: " + jsonObject1.getInteger("studentAge"));
	}
	
	//方式二
	Iterator<Object> iterator = jsonArray.iterator();
	while (iterator.hasNext()){
    	JSONObject jsonObject2 = (JSONObject) iterator.next();
    	System.out.println("studentName: " + jsonObject2.getString("studentName") + ",StudentAge: " + jsonObject2.getInteger("studentAge"));
        }
    }

4、JSONArray 转 json 字符串

public void JSONArrayToJSONString(){
	//json字符串-数组类型
    String  JSON_ARRAY_STR = "[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]";
	JSONArray jsonArray = JSON.parseArray(JSON_ARRAY_STR);
    String s = JSON.toJSONString(jsonArray);
    System.out.println(s);
}

5、复杂JSON格式字符串转 JSONObject

public void JSONStringTOJSONObject(){
	//复杂格式json字符串
    private static final String  COMPLEX_JSON_STR = "{\"teacherName\":\"crystall\"," +
            "\"teacherAge\":27,\"course\":{\"courseName\":\"english\",\"code\":1270},\"students\":[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]}";
	JSONObject jsonObject = JSON.parseObject(COMPLEX_JSON_STR);
    // 获取简单对象
    String teacherName = jsonObject.getString("teacherName");
    Integer teacherAge = jsonObject.getInteger("teacherAge");
    System.out.println("teacherName: " + teacherName + ",teacherAge " + teacherAge);
    
    // 获取JSONObject对象
    JSONObject course = jsonObject.getJSONObject("course");
    
    // 获取JSONObject中的数据
    String courseName = course.getString("courseName");
    Integer code = course.getInteger("code");
    System.out.println("courseName:  " + courseName + "   code:  " + code);
    
    // 获取JSONArray对象
    JSONArray students = jsonObject.getJSONArray("students");
    
    // 获取JSONArray的中的数据
    Iterator<Object> iterator = students.iterator();
    while (iterator.hasNext()){
    	JSONObject jsonObject1 = (JSONObject) iterator.next();
        System.out.println("studentName: " + jsonObject1.getString("studentName") + ",StudentAge: "
                    + jsonObject1.getInteger("studentAge"));
    }}  

6、复杂JSONObject 转 json字符串

public void JSONObjectTOJSON(){
	//复杂格式json字符串
    private static final String  COMPLEX_JSON_STR = "{\"teacherName\":\"crystall\"," +
            "\"teacherAge\":27,\"course\":{\"courseName\":\"english\",\"code\":1270},\"students\":[{\"studentName\":\"lily\",\"studentAge\":12},{\"studentName\":\"lucy\",\"studentAge\":15}]}";
	JSONObject jsonObject = JSON.parseObject(COMPLEX_JSON_STR);
    String s = JSON.toJSONString(jsonObject);
    System.out.println(s);
}

7、json字符串转 JavaBean

public class Student {
    private String studentName;
    private int studentAge;
}

public class Teacher {
    private String teacherName;
    private int teacherAge;
    private Course course;
    private List<Student> students;}

public class Course {
    private String courseName;
    private int code;
}

转换:

public void JSONStringToJavaBeanObj(){
	String  JSON_OBJ_STR = "{\"studentName\":\"lily\",\"studentAge\":12}";
	// 第一种方式
    JSONObject jsonObject = JSON.parseObject(JSON_OBJ_STR);
    String studentName = jsonObject.getString("studentName");
    Integer studentAge = jsonObject.getInteger("studentAge");
    Student student = new Student(studentName, studentAge);
    
    // 第二种方式:使用TypeReference<T>类,由于其构造方法使用protected进行修饰,故创建其子类
    Student student1 = JSON.parseObject(JSON_OBJ_STR, new TypeReference<Student>() {});
    
    // 第三种方式:通过反射(推荐)
    Student student2 = JSON.parseObject(JSON_OBJ_STR, Student.class);}

8、JavaBean 转 json 字符串

public void JavaBeanToJsonString(){
	Student lily = new Student("lily", 12);
    String s = JSON.toJSONString(lily);
    System.out.println(s);
}

9、json 字符串数组转 JavaBean-List

public void JSONStrToJavaBeanList(){
	// 方式一:
    JSONArray jsonArray = JSON.parseArray(JSON_ARRAY_STR);
    //遍历JSONArray
    List<Student> students = new ArrayList<Student>();
    Iterator<Object> iterator = jsonArray.iterator();
    while (iterator.hasNext()){
    	JSONObject next = (JSONObject) iterator.next();
        String studentName = next.getString("studentName");
        Integer studentAge = next.getInteger("studentAge");
        Student student = new Student(studentName, studentAge);
        students.add(student);
    }
    
    // 方式二,使用TypeReference<T>类,由于其构造方法使用protected进行修饰,故创建其子类
    List<Student> studentList = JSON.parseObject(JSON_ARRAY_STR,new TypeReference<ArrayList<Student>>() {});
    
    // 方式三,使用反射
    List<Student> students1 = JSON.parseArray(JSON_ARRAY_STR, Student.class);
    System.out.println(students1);}

10、JavaBean-List 转 json 字符串数组

public void JavaBeanListToJSONStr(){​
	Student student = new Student("lily", 12);
    Student student1 = new Student("lucy", 13);
    List<Student> students = new ArrayList<Student>();
​	students.add(student);
​	students.add(student1);
	​String s = JSON.toJSONString(student);
​	System.out.println(s);
}

11、复杂嵌套json格式字符串转 JavaBean_obj

public void ComplexJsonStrToJavaBean(){
    //第一种方式,使用TypeReference<T>类,由于其构造方法使用protected进行修饰,故创建其子类
    Teacher teacher = JSON.parseObject(COMPLEX_JSON_STR, new TypeReference<Teacher>() {});
   
   // 第二种方式,使用反射
   Teacher teacher1 = JSON.parseObject(COMPLEX_JSON_STR, Teacher.class);
}

12、JavaBean_obj 转复杂 json 格式字符串

public void JavaBeanToComplexJSONStr(){
    Teacher teacher = JSON.parseObject(COMPLEX_JSON_STR, Teacher.class);
    String s = JSON.toJSONString(teacher);
    System.out.println(s);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值