基础
1.jackson的github地址:https://github.com/FasterXML/jackson
2.jackson共有1.x和2.x两个版本系列, 其中1.x已废弃不再有版本发布, 2.x是活跃版本, 1.x和2.x并不兼容但也不冲突可以同时使用
3.jackson有三个核心模块
jackson-core -> 低阶API库,提供流式解析工具JsonParser,流式生成工具JsonGenerator
jackson-annotations -> jackson注解
jackson-databind -> 基于java对象的序列化, 反序列化能力, 需要前面两个模块的支持才能实现
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.13.3</version>
</dependency>
spring boot 已经自动集成 如果是Spring 项目根本不需要引依赖
jackson-core 相关知识
相关核心API
private static JsonFactory jsonFactory = new JsonFactory(); // 线程安全的 可以全局公用一个
/**
* jsonStr to Object
* 反序列化测试(JSON STR -> Object),入参是JSON字符串
*/
private static Object deserializeJSONByStr(String jsonString) {
JsonParser jsonParser = null;
Object object = new Object(); // 可以声明自己想要的对象类型 然后返回 就是转换成指定类型
try {
jsonParser = jsonFactory.createParser(jsonString);
if (jsonParser.nextToken() != JsonToken.START_OBJECT) {
jsonParser.close();
throw new IOException("起始位置没有大括号{");
}
while ( jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jsonParser.getCurrentName(); // 当前正在解析字段
jsonParser.nextToken(); // * next 解析下一个
/**
* 可以获取多种类型
* jsonParser.getLongValue()
* jsonParser.getText()
* jsonParser.getIntValue()
* jsonParser.getBooleanValue()
*/
String fieldValue = jsonParser.getValueAsString();
System.out.println(fieldName + "->" + fieldValue);
}
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
/**
* 序列化测试(Object -> JSON)
*
* @return 由对象序列化得到的JSON字符串
*/
public static String serialize(Map<String, Object> obj) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (JsonGenerator jsonGenerator = jsonFactory.createGenerator(byteArrayOutputStream, JsonEncoding.UTF8)) {
jsonGenerator.useDefaultPrettyPrinter();
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField("id", (int) obj.get("id"));
jsonGenerator.writeStringField("str", (String) obj.get("str"));
jsonGenerator.writeEndObject();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toString();
}
-------------------------------------------------------------------测试类---------------------------------------------
package com.study.other;
import com.fasterxml.jackson.core.*;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
public class JacksonCoreTest {
public static void main(String[] args) {
String str = "{\"aaa\":\"1\", \"bbb\":2}";
System.out.println(deserializeJSONByStr(str));
Map<String, Object> obj = new HashMap<>();
obj.put("id", 1);
obj.put("str", "2");
System.out.println(serialize(obj));
}
private static JsonFactory jsonFactory = new JsonFactory();
/**
* 序列化测试(Object -> JSON)
*
* @return 由对象序列化得到的JSON字符串
*/
public static String serialize(Map<String, Object> obj) {
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
try (JsonGenerator jsonGenerator = jsonFactory.createGenerator(byteArrayOutputStream, JsonEncoding.UTF8)) {
jsonGenerator.useDefaultPrettyPrinter();
jsonGenerator.writeStartObject();
jsonGenerator.writeNumberField("id", (int) obj.get("id"));
jsonGenerator.writeStringField("str", (String) obj.get("str"));
jsonGenerator.writeEndObject();
} catch (IOException e) {
e.printStackTrace();
}
return byteArrayOutputStream.toString();
}
// jsonStr to Object
private static Object deserializeJSONByStr(String jsonString) {
JsonParser jsonParser = null;
Object object = new Object(); // 可以声明自己想要的对象类型 然后返回 就是转换成指定类型
try {
jsonParser = jsonFactory.createParser(jsonString);
if (jsonParser.nextToken() != JsonToken.START_OBJECT) {
jsonParser.close();
throw new IOException("起始位置没有大括号{");
}
while (jsonParser.nextToken() != JsonToken.END_OBJECT) {
String fieldName = jsonParser.getCurrentName(); // 当前正在解析字段
jsonParser.nextToken(); // * next 解析下一个
/**
* 可以获取多种类型
* jsonParser.getLongValue()
* jsonParser.getText()
* jsonParser.getIntValue()
* jsonParser.getBooleanValue()
*/
String fieldValue = jsonParser.getValueAsString();
System.out.println(fieldName + "->" + fieldValue);
}
} catch (Exception e) {
e.printStackTrace();
}
return object;
}
}
常用相关API
package com.study.other;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.util.*;
public class JacksonAPIDemo {
public static void main(String[] args) throws Exception {
ObjectMapper mapper = new ObjectMapper();
TestVO testVO = new TestVO();
testVO.setId(1);
testVO.setAaa("aaa");
testVO.setBbb(new Date());
TestVO testVO2 = new TestVO();
testVO2.setId(2);
testVO2.setAaa("bbb");
testVO2.setBbb(new Date());
String jsonStr = mapper.writeValueAsString(testVO);
System.out.println("对象序列化成字符串-->" + jsonStr);
String testVOJsonStr = "{\"id\":2," +
"\"aaa\":\"bbb\"," +
"\"bbb\":1655513110837}";
// 字符串 -> 对象
TestVO testVOR1 = mapper.readValue(jsonStr, TestVO.class);
System.out.println("反序列化--->" + testVOR1);
// 对象 -> 文件
// mapper.writeValue(new File("testVO.json"), testVOR1);
// 文件 -> 对象
// TestVO testVO2 = mapper.readValue(new File("testVO.json"), TestVO.class);
// System.out.println(testVO2);
// 对象 -> byte数组
// byte[] array = mapper.writeValueAsBytes(testVOR1);
// System.out.println("111->" + Arrays.toString(array));
// byte数组 -> 对象
// TestVO testVO3 = mapper.readValue(array, TestVO.class);
// 字符串网络地址 -> 对象
// mapper.readValue(new URL(jsonDataUrl), TestVO.class);
System.out.println("-------------------------------------------------集合序列化相关API----------------------------------------------------");
Map<String, Object> root = new HashMap<>(8);
root.put("id", 1);
root.put("aaa", "s1");
Map<String, String> child = new HashMap<>();
child.put("a","a");
child.put("b", "b");
root.put("child", child);
String mapTestJsonStr = mapper.writeValueAsString(root);
System.out.println("HashMap序列化的字符串---->" + mapTestJsonStr);
Map<String, Object> mapFromStr = mapper.readValue(mapTestJsonStr, new TypeReference<Map<String, Object>>() {});
System.out.println("HashMap反序列化---->" + mapFromStr);
// JsonNode类型操作
JsonNode jsonNode = mapper.readTree(mapTestJsonStr);
System.out.println(jsonNode.get("child").get("a").asText());
List<TestVO> list = new ArrayList<>(2);
list.add(testVO);
list.add(testVO2);
String listStr = mapper.writeValueAsString(list);
System.out.println("listStr->" + listStr);
// json数组 -> 对象数组
TestVO[] testVOArray = mapper.readValue(listStr, TestVO[].class);
System.out.println("testVOArray--->" + Arrays.toString(testVOArray));
// json数组 -> 对象集合
List<TestVO> testVOList = mapper.readValue(listStr, new TypeReference<List<TestVO>>() {});
System.out.println("testVOList--->" + testVOList);
}
}
平时可能用到的自定义配置项说明:
1.反序列化时,遇到未知属性不要抛出异常:
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
2.空对象不要抛出异常:
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
3反序列化时,空字符串对于的实例属性为null:
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);
4.序列化结果格式化:
mapper.enable(SerializationFeature.INDENT_OUTPUT);
5.Date、Calendar等序列化为时间格式的字符串(如果不执行以下设置,就会序列化成时间戳格式):
mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
6.允许C和C++样式注释:
mapper.configure(JsonParser.Feature.ALLOW_COMMENTS, true);
7.允许字段名没有引号(可以进一步减小json体积):
mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true);
8.允许单引号:
mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
9. 配合@JsonRootName(value = "xxx")注解使用 外层增加JSON嵌套注解
mapper.enable(SerializationFeature.WRAP_ROOT_VALUE); // 用于序列化 没有JsonRootName注解 有默认值Order1
mapper.enable(SerializationFeature.UNWRAP_ROOT_VALUE); // 用于反序列化 反序列化必须JsonRootName必须存在
实际工作相关
package com.study.other;
import com.fasterxml.jackson.annotation.JsonFilter;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.databind.ser.BeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.FilterProvider;
import com.fasterxml.jackson.databind.ser.PropertyFilter;
import com.fasterxml.jackson.databind.ser.PropertyWriter;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import java.util.*;
public class JacksonWorkTest {
static class DTO {
private int id;
private String aaa;
private String bbb;
private DTO1 ccc;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getAaa() {
return aaa;
}
public void setAaa(String aaa) {
this.aaa = aaa;
}
public String getBbb() {
return bbb;
}
public void setBbb(String bbb) {
this.bbb = bbb;
}
public DTO1 getCcc() {
return ccc;
}
public void setCcc(DTO1 ccc) {
this.ccc = ccc;
}
@Override
public String toString() {
return "DTO{" +
"id=" + id +
", aaa='" + aaa + '\'' +
", bbb='" + bbb + '\'' +
", ccc='" + ccc + '\'' +
'}';
}
}
static class DTO1 {
private int id1;
private String aaa1;
private String bbb1;
public int getId1() {
return id1;
}
public void setId1(int id1) {
this.id1 = id1;
}
public String getAaa1() {
return aaa1;
}
public void setAaa1(String aaa1) {
this.aaa1 = aaa1;
}
public String getBbb1() {
return bbb1;
}
public void setBbb1(String bbb1) {
this.bbb1 = bbb1;
}
@Override
public String toString() {
return "DTO1{" +
"id1=" + id1 +
", aaa1='" + aaa1 + '\'' +
", bbb1='" + bbb1 + '\'' +
'}';
}
}
@JsonFilter("JsonFilterUtilByCm")
static class JsonFilterUtilByCm extends FilterProvider {
Map<Class<?>, Set<String>> includeMap = new HashMap<>();
Map<Class<?>, Set<String>> filterMap = new HashMap<>();
public void include(Class<?> type, String[] fields) {
addToMap(includeMap, type, fields);
}
public void filter(Class<?> type, String[] fields) {
addToMap(filterMap, type, fields);
}
private void addToMap(Map<Class<?>, Set<String>> map, Class<?> type, String[] fields) {
Set<String> fieldSet = map.getOrDefault(type, new HashSet<>());
fieldSet.addAll(Arrays.asList(fields));
map.put(type, fieldSet);
}
@Override
public BeanPropertyFilter findFilter(Object filterId) {
throw new UnsupportedOperationException("Access to deprecated filters not supported");
}
@Override
public PropertyFilter findPropertyFilter(Object filterId, Object valueToFilter) {
return new SimpleBeanPropertyFilter() {
@Override
public void serializeAsField(Object pojo, JsonGenerator jsonGenerator, SerializerProvider provider, PropertyWriter writer)
throws Exception {
if (apply(pojo.getClass(), writer.getName())) {
writer.serializeAsField(pojo, jsonGenerator, provider);
} else if (!jsonGenerator.canOmitFields()) {
writer.serializeAsOmittedField(pojo, jsonGenerator, provider);
}
}
};
}
public boolean apply(Class<?> type, String name) {
Set<String> includeFields = includeMap.get(type);
Set<String> filterFields = filterMap.get(type);
if (includeFields != null && includeFields.contains(name)) {
return true;
} else if (filterFields != null && !filterFields.contains(name)) {
return true;
} else if (includeFields == null && filterFields == null) {
return true;
}
return false;
}
}
// 测试实际工作中的序列化问题
private static void test1() {
ObjectMapper objectMapper = new ObjectMapper();
DTO1 ccc = new DTO1();
ccc.setId1(2);
DTO dto = new DTO();
dto.setId(1);
dto.setBbb("bbb");
dto.setCcc(ccc);
JsonFilterUtilByCm jacksonFilterUtil = new JsonFilterUtilByCm();
jacksonFilterUtil.include(dto.getClass(), new String[]{"id", "aaa", "ccc"});
jacksonFilterUtil.include(ccc.getClass(), new String[]{"id", "aaa1"});
objectMapper.setFilterProvider(jacksonFilterUtil);
objectMapper.addMixIn(DTO.class, JsonFilterUtilByCm.class);
objectMapper.addMixIn(DTO1.class, JsonFilterUtilByCm.class);
try {
System.out.println(objectMapper.writeValueAsString(dto));
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
// 测试实际工作中的反序列化问题
private static void test2() {
String str = "{\"id\":1,\"aaa\":null,\"ccc\":{\"aaa1\":null}}";
ObjectMapper objectMapper = new ObjectMapper();
try {
DTO obj = objectMapper.readValue(str, DTO.class);
System.out.println(obj);
System.out.println(obj.getAaa());
} catch (JsonProcessingException e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
// test1();
test2();
}
}
网友评论