文章目录
记录下Jackson常用的功能
Jackson组成
jackson是java处理json的标准库
Jackson核心有三个包
core,annotation,databind, databind依赖前两者,所以使用时直接引入databind即可
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.17.0</version>
</dependency>
JSON和对象系列
JSON和POJO互转示例
使用ObjectMapper进行JSON字符串和类,List,Map的互转,字段若私有,则需提供getter和setter方法
ObjectMapper objectMapper = new ObjectMapper();
Information information = new Information();
information.setHost("12414142");
information.setN ame("111");
information.setPassword("123");
Email email = new Email();
email.setTitle("email-1");
email.setInformation(information);
String string = objectMapper.writeValueAsString(email);
System.out.println(string);
Email email1 = objectMapper.readValue(string, Email.class);
System.out.println(email1);
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});
Map<String, Object> map
= objectMapper.readValue(json, new TypeReference<Map<String,Object>>(){});
public class Email {
private Information information;
private String title;
public Information getInformation() {
return information;
}
public void setInformation(Information information) {
this.information = information;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
}
public class Information {
private String name;
private String password;
private String host;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
}
// Note: can use getters/setters as well; here we just use public fields directly:
public class MyValue {
public String name;
public int age;
// NOTE: if using getters/setters, can keep fields `protected` or `private`
}
TreeNode和ObjectNode
针对非对象类,动态场景,动态字段场景
// can be read as generic JsonNode, if it can be Object or Array; or,
// if known to be Object, as ObjectNode, if array, ArrayNode etc:
JsonNode root = mapper.readTree("{ \"name\": \"Joe\", \"age\": 13 }");
String name = root.get("name").asText();
int age = root.get("age").asInt();
// can modify as well: this adds child Object as property 'other', set property 'type'
root.withObject("/other").put("type", "student");
String json = mapper.writeValueAsString(root); // prints below
/*
with above, we end up with something like as 'json' String:
{
"name" : "Bob",
"age" : 13,
"other" : {
"type" : "student"
}
}
*/
// Some parts of this json are modeled in our code, some are not
JsonNode root = mapper.readTree(complexJson);
Person p = mapper.treeToValue(root.get("person"), Person.class); // known single pojo
Map<String, Object> dynamicmetadata = mapper.treeToValue(root.get("dynamicmetadata"), Map.class); // unknown smallish subfield, convert all to collections
int singledeep = root.get("deep").get("large").get("hiearchy").get("important").intValue(); // single value in very deep optional subfield, ignoring the rest
int singledeeppath = root.at("/deep/large/hiearchy/important").intValue(); // json path
int singledeeppathunique = root.findValue("important").intValue(); // by unique field name
// Send an aggregate json from heterogenous sources
ObjectNode root = mapper.createObjectNode();
root.putPOJO("person", new Person("Joe")); // simple pojo
root.putPOJO("friends", List.of(new Person("Jane"), new Person("Jack"))); // generics
Map<String, Object> dynamicmetadata = Map.of("Some", "Metadata");
root.putPOJO("dynamicmetadata", dynamicmetadata); // collections
root.putPOJO("dynamicmetadata", mapper.valueToTree(dynamicmetadata)); // same thing
root.set("dynamicmetadata", mapper.valueToTree(dynamicmetadata)); // same thing
root.withObject("deep").withObject("large").withObject("hiearchy").put("important", 42); // create as you go
root.withObject("/deep/large/hiearchy").put("important", 42); // json path
mapper.writeValueAsString(root);
配置
未知字段
//反序列化时候忽略未知字段(多的字段)
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Car car = objectMapper.readValue(jsonString, Car.class);
JsonNode jsonNodeRoot = objectMapper.readTree(jsonString);
JsonNode jsonNodeYear = jsonNodeRoot.get("year");
String year = jsonNodeYear.asText();
//单个类反序列化时忽略未知字段
@JsonIgnoreProperties(ignoreUnknown = true)
public class MyDtoIgnoreUnknown { ... }
//反序列化时支持反序列化不完整的JSON
//设置是否允许基础字段为null
objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false);
//是否允许将枚举值序列化/反序列化为数字
objectMapper.configure(DeserializationFeature.FAIL_ON_NUMBERS_FOR_ENUMS, false);
忽略字段
基本都要用对应注解,
四个维度:类,字段,过滤器,类型字段忽略
忽略null值
1.配置单个类或者单个字段用相应注解
2.mapper上配置
mapper.setSerializationInclusion(Include.NON_NULL);
字段别名
@JsonProperty注解
使用自定义序列化和反序列化
public class CustomCarSerializer extends StdSerializer<Car> {
public CustomCarSerializer() {
this(null);
}
public CustomCarSerializer(Class<Car> t) {
super(t);
}
@Override
public void serialize(
Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) {
jsonGenerator.writeStartObject();
jsonGenerator.writeStringField("car_brand", car.getType());
jsonGenerator.writeEndObject();
}
}
public class CustomCarDeserializer extends StdDeserializer<Car> {
public CustomCarDeserializer() {
this(null);
}
public CustomCarDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Car deserialize(JsonParser parser, DeserializationContext deserializer) {
Car car = new Car();
ObjectCodec codec = parser.getCodec();
JsonNode node = codec.readTree(parser);
// try catch block
JsonNode colorNode = node.get("color");
String color = colorNode.asText();
car.setColor(color);
return car;
}
}
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
module.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(module);
Car car = new Car("yellow", "renault");
String carJson = mapper.writeValueAsString(car);
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
ObjectMapper mapper = new ObjectMapper();
SimpleModule module =
new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
module.addDeserializer(Car.class, new CustomCarDeserializer());
mapper.registerModule(module);
Car car = mapper.readValue(json, Car.class);
处理日期格式
ObjectMapper objectMapper = new ObjectMapper();
DateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm a z");
objectMapper.setDateFormat(df);
String carAsString = objectMapper.writeValueAsString(request);
// 输出: {"car":{"color":"yellow","type":"renault"},"datePurchased":"2016-07-03 11:43 AM CEST"}
类型转换
// Convert from List<Integer> to int[]
List<Integer> sourceList = ...;
int[] ints = mapper.convertValue(sourceList, int[].class);
// Convert a POJO into Map!
Map<String,Object> propertyMap = mapper.convertValue(pojoValue, Map.class);
// ... and back
PojoType pojo = mapper.convertValue(propertyMap, PojoType.class);
// decode Base64! (default byte[] representation is base64-encoded String)
String base64 = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz";
byte[] binary = mapper.convertValue(base64, byte[].class);
XML和对象系列
xml依赖
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.17.0</version>
</dependency>
序列化字符串
XmlMapper xmlMapper = new XmlMapper();
String xml = xmlMapper.writeValueAsString(new Person());
反序列化字符串
XmlMapper xmlMapper = new XmlMapper();
SimpleBean value
= xmlMapper.readValue("<SimpleBean><x>1</x><y>2</y></SimpleBean>", SimpleBean.class);
序列化xml文件
xmlMapper.writeValue(new File("person_bean.xml"), new Person());
反序列化xml文件
XmlMapper xmlMapper = new XmlMapper();
String xml = inputStreamToString(new FileInputStream(file));
SimpleBean value = xmlMapper.readValue(xml, SimpleBean.class);
public String inputStreamToString(InputStream is) throws IOException {
StringBuilder sb = new StringBuilder();
String line;
BufferedReader br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
br.close();
return sb.toString();
}
List和xml的序列化和反序列化
<Person>
<firstName>Rohan</firstName>
<lastName>Daye</lastName>
<phoneNumbers>
<phoneNumbers>9911034731</phoneNumbers>
<phoneNumbers>9911033478</phoneNumbers>
</phoneNumbers>
<address>
<streetName>Name1</streetName>
<city>City1</city>
</address>
<address>
<streetName>Name2</streetName>
<city>City2</city>
</address>
</Person>
public final class Person {
private String firstName;
private String lastName;
private List<String> phoneNumbers = new ArrayList<>();
@JacksonXmlElementWrapper(useWrapping = false)
private List<Address> address = new ArrayList<>();
//standard setters and getters
}
XmlMapper xmlMapper = new XmlMapper();
Person person = testPerson(); // test data
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
xmlMapper.writeValue(byteArrayOutputStream, person);
高级特性
自定义序列化器根据属性值有条件的序列化对象
枚举类序列化和反序列化
//默认输出序列化枚举类 枚举名称
https://baeldung-cn.com/jackson-serialize-enums#45-%E8%87%AA%E5%AE%9A%E4%B9%89%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96%E5%99%A8
字段可见性
有两个维度,全局维度配置和类维度
objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class MyDtoNoAccessors { ... }
比较JSON对象
JsonNode.equals()
// Jackson还提供了JsonNode.equals(comparator, JsonNode),以配置自定义Java比较器对象。
//可以自定义比较器实现自己的比较逻辑