SpringBoot默认使用Jackson,它与ObjectMapper的前世今生&JSON工具(格式化、JSONObject转对象)
Jackson与ObjectMapper1、Jackson可以轻松地将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象;2、ObjectMapper类是Jackson库的主要类。它称为ObjectMapper的原因是因为它将JSON映射为Java对象(序列化),或将Java对象映射到JSON(序列化)。ObjectMapper是线程安全的,应尽可能重用。=
Jackson与ObjectMapper
1、Jackson可以轻松地将Java对象转换成json对象和xml文档,同样也可以将json、xml转换成Java对象;
2、ObjectMapper类是Jackson库的主要类。它称为ObjectMapper的原因是因为它将JSON映射为Java对象(序列化),或将Java对象映射到JSON(序列化)。
ObjectMapper是线程安全的,应尽可能重用。=====> 统一配置
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
@Configuration
public class ObjectMapperConfig {
@Bean
@Primary
public ObjectMapper objectMapper(){
ObjectMapper mapper = new ObjectMapper(); // new 的过程比较耗时
// 忽略json字符串中不识别的字段
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
// 其他需求,按需配置
return mapper;
}
}
Jackson中的常用注解
@JsonIgnore 标注在字段上,序列化时忽略的字段
@JsonProperty 标注在字段上,序列化时按自定义的字段序列化
@JsonFormat 标注在时间类型(Date)字段上,序列化时按指定的日期格式序列化
@JsonInclude 标注在类上,序列化时按自定义的特性处理
@JsonIgnoreProperties 标注在类上,序列化时要忽略的类的属性字段,支持多个
@JsonSerialize
枚举类定义
package coupon;
import lombok.AllArgsConstructor;
import lombok.Getter;
@Getter
@AllArgsConstructor
public enum CouponEnum {
USABLE("可用的", 0),
USED("已使用", 1);
private String desc;
private Integer code;
}
类定义
package coupon;
import com.fasterxml.jackson.annotation.*;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import lombok.experimental.Accessors;
import java.util.Date;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
@JsonInclude(JsonInclude.Include.NON_NULL) // 不允许序列化的值为null
@JsonIgnoreProperties({"couponCode"})
public class Coupon {
@JsonIgnore
private Long id;
@JsonProperty("user_id")
private Long userId;
private String couponCode;
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy/MM/dd hh:mm:ss")
private Date assignTime;
private CouponEnum couponEnum;
private CouponTemplate couponTemplate;
@Data
@AllArgsConstructor
@NoArgsConstructor
@Accessors(chain = true)
public static class CouponTemplate{
private String name;
private String logo;
}
public static Coupon fake(){
return new Coupon(
1L, 100L, "Merchant_01", new Date(),
CouponEnum.USED,
new CouponTemplate("全品券", "All_used")
);
}
}
测试
pom里引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
package com.insight.cloudeureka;
import com.fasterxml.jackson.databind.ObjectMapper;
import coupon.Coupon;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
@SpringBootTest
@RunWith(SpringRunner.class)
@Slf4j
public class JsonAnnoTest {
@Autowired
private ObjectMapper mapper;
@Test
public void testJacksonAnno() throws Exception{
Coupon coupon = Coupon.fake();
coupon.setCouponTemplate(null);
// {"assignTime":"2021/07/18 05:11:20","couponEnum":"USED","user_id":100}
log.info("ObjectMapper se Coupon: {}", mapper.writeValueAsString(coupon));
}
}
ObjectMapper 反序列化用readValue方法
测试结果
实现JsonSerializer<T>
package coupon;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.SerializerProvider;
import java.io.IOException;
import java.text.SimpleDateFormat;
public class CouponSerialize extends JsonSerializer<Coupon> {
@Override
public void serialize(Coupon coupon, JsonGenerator generator, SerializerProvider serializerProvider) throws IOException {
// 开始序列化
generator.writeStartObject();
generator.writeStringField("id", String.valueOf(coupon.getId()));
generator.writeStringField("userId", coupon.getUserId().toString());
generator.writeStringField("couponCode", coupon.getCouponCode());
generator.writeStringField("assignTime", new SimpleDateFormat("yyyy/MM/dd HH:mm:ss").format(coupon.getAssignTime()));
generator.writeStringField("couponEnum",coupon.getCouponEnum().getDesc());
generator.writeStringField("name", coupon.getCouponTemplate().getName());
generator.writeStringField("logo", coupon.getCouponTemplate().getLogo());
// 结束序列化
generator.writeEndObject();
}
}
如果自己实现序列化,那么需要将类上的注解&字段上的JSON注解去掉
一个注解完成多个注解的功能。
不去掉类的相关JSON注解,会输出,与上对比可知,自己实现的接口,并没有起作用!
{"assignTime":"2021/07/18 06:53:29","couponEnum":"USED","couponTemplate":{"name":"全品券","logo":"All_used"},"user_id":100}
JSON工具(格式化、JSONObject转对象)
public class JsonUtil {
public static <T> BaseRet<T> convert2BaseRet(String json, Class... classes) {
ParameterizedTypeImpl beforeType = null;
if (classes.length != 0) {
//支持多级泛型的解析
for (int i = classes.length - 1; i > 0; i--) {
beforeType = new ParameterizedTypeImpl(new Type[]{beforeType == null ? classes[i] : beforeType},
null, classes[i - 1]);
}
}
return JSON.parseObject(json, beforeType);
}
public static String formatJson(String jsonStr) {
if (null != jsonStr && !"".equals(jsonStr)) {
StringBuilder sb = new StringBuilder();
char current = 0;
int indent = 0;
for (int i = 0; i < jsonStr.length(); ++i) {
char last = current;
current = jsonStr.charAt(i);
switch (current) {
case ',':
sb.append(current);
if (last != '\\') {
sb.append('\n');
addIndentBlank(sb, indent);
}
break;
case '[':
case '{':
sb.append(current);
sb.append('\n');
++indent;
addIndentBlank(sb, indent);
break;
case ']':
case '}':
sb.append('\n');
--indent;
addIndentBlank(sb, indent);
sb.append(current);
break;
default:
sb.append(current);
}
}
return sb.toString();
} else {
return "";
}
}
private static void addIndentBlank(StringBuilder sb, int indent) {
for (int i = 0; i < indent; ++i) {
sb.append('\t');
}
}
public static JSONObject toJSONObject(T t){
return JSONObject.parseObject(JSON.toJSONString(t));
}
public static T toClass(JSONObject jsonObject,Class<T> claz){
return JSONObject.parseObject(jsonObject.toJSONString(),claz);
}
}
更多推荐
所有评论(0)