准备
实体类User
1 2 3 4 5 6 7 8 9 10 11 12 public class User implements Serializable { private static final long serialVersionUID = -3180230416244251692L ; private Integer id; private String name; private Date birth; }
ObjectMapper API
序列化与反序列化 序列化属性SerializationFeature
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 WRAP_ROOT_VALUE(false ), INDENT_OUTPUT(false ), FAIL_ON_EMPTY_BEANS(true ), FAIL_ON_SELF_REFERENCES(true ), WRAP_EXCEPTIONS(true ), FAIL_ON_UNWRAPPED_TYPE_IDENTIFIERS(true ), CLOSE_CLOSEABLE(false ), FLUSH_AFTER_WRITE_VALUE(true ), WRITE_DATES_AS_TIMESTAMPS(true ), WRITE_DATE_KEYS_AS_TIMESTAMPS(false ), WRITE_DATES_WITH_ZONE_ID(false ), WRITE_DURATIONS_AS_TIMESTAMPS(true ), WRITE_CHAR_ARRAYS_AS_JSON_ARRAYS(false ), WRITE_ENUMS_USING_TO_STRING(false ), WRITE_ENUMS_USING_INDEX(false ), WRITE_ENUM_KEYS_USING_INDEX(false ), WRITE_SINGLE_ELEM_ARRAYS_UNWRAPPED(false ), WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS(true ), ORDER_MAP_ENTRIES_BY_KEYS(false ), EAGER_SERIALIZER_FETCH(true ), USE_EQUALITY_FOR_OBJECT_ID(false );
反序列化属性DeserializationFeature
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 USE_BIG_DECIMAL_FOR_FLOATS(false ), USE_BIG_INTEGER_FOR_INTS(false ), USE_LONG_FOR_INTS(false ), USE_JAVA_ARRAY_FOR_JSON_ARRAY(false ), FAIL_ON_UNKNOWN_PROPERTIES(true ), FAIL_ON_NULL_FOR_PRIMITIVES(false ), FAIL_ON_NUMBERS_FOR_ENUMS(false ), FAIL_ON_INVALID_SUBTYPE(true ), FAIL_ON_READING_DUP_TREE_KEY(false ), FAIL_ON_IGNORED_PROPERTIES(false ), FAIL_ON_UNRESOLVED_OBJECT_IDS(true ), FAIL_ON_MISSING_CREATOR_PROPERTIES(false ), FAIL_ON_NULL_CREATOR_PROPERTIES(false ), FAIL_ON_MISSING_EXTERNAL_TYPE_ID_PROPERTY(true ), FAIL_ON_TRAILING_TOKENS(false ), WRAP_EXCEPTIONS(true ), ACCEPT_SINGLE_VALUE_AS_ARRAY(false ), UNWRAP_SINGLE_VALUE_ARRAYS(false ), UNWRAP_ROOT_VALUE(false ), ACCEPT_EMPTY_STRING_AS_NULL_OBJECT(false ), ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT(false ), ACCEPT_FLOAT_AS_INT(true ), READ_ENUMS_USING_TO_STRING(false ), READ_UNKNOWN_ENUM_VALUES_AS_NULL(false ), READ_UNKNOWN_ENUM_VALUES_USING_DEFAULT_VALUE(false ), READ_DATE_TIMESTAMPS_AS_NANOSECONDS(true ), ADJUST_DATES_TO_CONTEXT_TIME_ZONE(true ), EAGER_DESERIALIZER_FETCH(true );
environment配置 可配置
spring.jackson.deserialization.=true|false
spring.jackson.generator.=true|false
spring.jackson.mapper.=true|false
spring.jackson.parser.=true|false
spring.jackson.serialization.=true|false
spring.jackson.serialization-inclusion=always|non_null|non_absent|non_default|non_empty
application.yml:
1 2 3 4 5 6 7 8 9 10 11 12 spring: jackson: date-format: yyyy-MM-dd HH:mm:ss default-property-inclusion: non_empty serialization: deserialization: parser:
configuration配置 在@Configuration类中生成bean:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 @Configuration public class JacksonConfig { @Bean @Primary @ConditionalOnMissingBean(ObjectMapper.class) public ObjectMapper objectMapper () { ObjectMapper objectMapper = new ObjectMapper(); objectMapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd" )); objectMapper.configure(MapperFeature.AUTO_DETECT_FIELDS, true ); objectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false ); objectMapper.configure(SerializationFeature.WRITE_ENUMS_USING_TO_STRING, true ); objectMapper.configure(SerializationFeature.WRITE_DATE_TIMESTAMPS_AS_NANOSECONDS, true ); objectMapper.configure(SerializationFeature.FLUSH_AFTER_WRITE_VALUE, true ); objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY); objectMapper.configure(DeserializationFeature.FAIL_ON_NULL_FOR_PRIMITIVES, false ); objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true ); objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false ); objectMapper.configure(DeserializationFeature.FAIL_ON_IGNORED_PROPERTIES, false ); objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_ARRAY_AS_NULL_OBJECT, true ); objectMapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true ); objectMapper.configure(DeserializationFeature.READ_DATE_TIMESTAMPS_AS_NANOSECONDS, true ); objectMapper.configure(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL, true ); objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true ); objectMapper.configure(DeserializationFeature.READ_ENUMS_USING_TO_STRING, true ); return objectMapper; } }
Rest接口:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 @RestController @RequestMapping("/user") public class UserController { private static Logger log = LoggerFactory.getLogger(UserController.class); @Autowired private ObjectMapper objectMapper; @GetMapping("/get") public String getUser () throws JsonProcessingException { User user = new User(1 , "KHighness" , new Date()); return objectMapper.writeValueAsString(user); } @PostMapping("/save") public void saveUser (@RequestBody String userJsonList) throws IOException { List<User> userList = objectMapper.readValue(userJsonList, new TypeReference<List<User>>() {}); userList.forEach(e -> {log.info(e.toString());}); } }
CURL测试(windows下建议使用cmd进行测试,用powershell会到导致POST错误) 序列化测试:
1 $ curl -X GET http://localhost:3333 /user/get
序列化测试结果:
1 {"id" :1 ,"name" :"KHighness" ,"birth" :"2021-04-15" }
反序列化测试:
1 $ curl -H "Content-Type:application/json" -X POST --data "[{\" id\":1, \" name\":\" Khighness\", \" birth\":\" 2001 -09 -11 \"}, {\" id\":2, \" name\":\" FlowerK\", \" birth\":\" 2003 -07 -24 \"}]" http://localhost:3333 /user/save
反序列化测试结果:
1 [{"id" :1 ,"name" :"Khighness" ,"birth" :"2001-09-11" },{"id" :2 ,"name" :"FlowerK" ,"birth" :"2003-07-24" }]
Jackson注解 (1)@JsonProperty 作用在属性上,用于序列化和反序列化时为JSON key指定一个别名。 例如:
1 2 @JsonProperty("bth") private Date birth;
此时序列化测试结果为:
1 {"id" :1 ,"name" :"KHighness" ,"bth" :"2021-04-16" }
(2)@JsonIgnore 作用在属性上,用于在序列化和反序列化时忽略此属性。 例如:
1 2 @JsonIgnore private String name;
此时序列化测试结果为:
1 {"id" :1 ,"birth" :"2021-04-16" }
(3)@JsonIgnoreProperties 作用在类上,用于忽略一组属性。 例如:
1 @JsonIgnoreProperties({"id", "birth"})
此时序列化测试结果为:
(4)@JsonFormat 作用在日期属性上,用于格式化。 例如:
1 2 @JsonFormat(pattern = "yyyy.MM.dd") private Date birth;
此时序列化测试结果为:
1 {"id" :1 ,"userName" :"KHighness" ,"birth" :"2021.04.16" }
(5)@JsonNaming 作用在类上,用于指定一个命名策略。
Jackson自带了五种(两种)命名策略,使用方式,
1 2 3 4 @JsonNaming(PropertyNamingStrategy.<Strategy>.class) public class User { private String userName; }
命名策略
中文描述
作用结果
KebabCaseStrategy
中划线
user-name
SnakeCaseStrategy
下划线
user_name
UpperCamelCaseStrategy
大驼峰
UserName
LowerCaseStrategy
全小写
username
LowerDotCaseStrategy
小写点
user.name
(6)@JsonSerialize 作用在类上,指定一个类来自定义序列化,该类必须实现JsonSerializer
接口。 例如:
1 2 3 4 5 6 7 8 9 public class UserSerializer extends JsonSerializer <User > { @Override public void serialize (User user, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException { jsonGenerator.writeStartObject(); jsonGenerator.writeStringField("USER-NAME" , user.getUserName()); jsonGenerator.writeEndObject(); } }
1 2 3 4 5 6 @JsonSerialize(using = UserSerializer.class) public class User implements Serializable { private static final long serialVersionUID = -3180230416244251692L ; private String userName; }
此时序列化接口测试结果为:
1 {"USER-NAME" :"KHighness" }
(7)@JsonDeserialize 作用在类上,指定一个类来自定义反序列化,该类必须实现JsonDeserializer
接口。 例如:
1 2 3 4 5 6 7 8 9 10 11 public class UserDeserializer extends JsonDeserializer <User > { @Override public User deserialize (JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException { JsonNode node = jsonParser.getCodec().readTree(jsonParser); String userName = node.get("user-name" ).asText(); User user = new User(); user.setUserName(userName); return user; } }
1 2 3 4 5 6 @JsonDeserialize(using = UserDeserializer.class) public class User implements Serializable { private static final long serialVersionUID = -3180230416244251692L ; private String userName; }
反序列化测试:
1 2 curl -H "Content-Type:application/json" -X POST --data "[{\"user-name\":\"Khighness\"}, {\"user-name\":\"FlowerK\"}]" http://localhost:3333/user/save [{"userName" :"Khighness" },{"userName" :"FlowerK" }]
反序列化测试结果为:
1 [{"userName" :"Khighness" },{"userName" :"FlowerK" }]
(8)@JsonView 作用在类、属性和方法上,用来序列化组。 比如对于User对象,某些情况下只返回userName即可,
而某些情况下需要返回全部属性。因此User对象可以这样定义:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 public class User implements Serializable { private static final long serialVersionUID = -3180230416244251692L ; public interface UserNameView {}; public interface AllUserFieldView extends UserNameView {}; @JsonView(AllUserFieldView.class) private Integer id; @JsonView(UserNameView.class) private String userName; @JsonView(AllUserFieldView.class) private Date birth; }
然后在controller的方法上使用@JsonView,可以指定序列化组名。 使用组名UserNameView:
1 2 3 4 5 6 @JsonView(User.UserNameView.class) @GetMapping("/get") public User getUser () throws JsonProcessingException { User user = new User(1 , "KHighness" , new Date()); return user; }
序列化测试结果为:
1 {"userName" :"KHighness" }
当组名指定为AllUserFieldView
时,序列化测试结果为:
1 {"id" :1 ,"userName" :"KHighness" ,"birth" :"2021-04-17" }
参考 [1] 🐦 SpringBoot中的JSON技术 [2] ☁️ 自定义Jackson ObjectMapper