Springboot+json序列化
- jackson方案
- fastjson方案
- gson方案
一、Jackson方案
- 注意:Springboot默认的json持久化是jackson
1、添加依赖
- 注意:除了jackson-core 其他都是选填
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9.3</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-annotations</artifactId>
<version>2.9.9</version>
</dependency>
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-xml</artifactId>
<version>2.9.9</version>
</dependency>
2、配置
2。1、配置项
#时间戳统一转换
spring:
jackson:
date-format: yyyy-MM-dd HH:mm:ss
time-zone: GMT+8
2.1 配置类
@Configuration
public class JacksonConfig {
@Value("${spring.jackson.data-format:yyyy-MM-dd HH:mm:ss}")
private String pattern;
// 日期序列化器
@Bean
public LocalDateTimeSerializer localDateTimeSerializer(){
return new LocalDateTimeSerializer(DateTimeFormatter.ofPattern(pattern));
}
// 日期反序列化器
@Bean
public Jackson2ObjectMapperBuilderCustomizer jackson2ObjectMapperBuilderCustomizer(){
return builder->builder
.serializerByType(LocalDateTime.class,localDateTimeSerializer());
}
}
3、Jackson注解使用
2.1、序列化注解:
- @JsonAnyGetter 将对象Map作为属性
- @JsonGetter 方法注解:将getter结果作为属性
- @JsonPropertyOrder 类注解:指定序列化后属性栓
- @JsonRawValue 序列化时将属性原样输出
- @JsonValue 方法注解:将方法的结果序列化
- @JsonRootName 类注解:为json加一个根属性
- @JsonSerialize 自定义序列化器
- @JsonInclude 类注解:序列化时排除null值
- @JsonAppend 序列化时增加一个虚拟属性
2.2、反序列化注解:
- @JacksonInject 注入属性
- @JsonDeserialize 自定义反序列化器
- @JsonAlias 反序列化别名
- @JsonIgnoreProperties 类注解,忽略属性
2.2、序列化和反序列化共用:
- @JsonIgnore 忽略属性
- @JsonIgnoreType 类注解,忽略属性类型,统一变成String
- @JsonInclude 类和属性:排除空属性
- @JsonProperty 方法注解:设置别名
- @JsonFormat 属性格式化,可格式化日期和金额,以及自定义格式化
- @JsonUnwrapped 去掉外包装根节点名称
- @JsonView 指定序列化和反序列化的视图级别
- @JsonManagedReference 解决不同属性的依赖关系
- @JsonBackReference 解决不同属性的依赖关系,防止循环调用
- @JsonFilter 序列化时指定一个过滤器
- @JsonNaming 属性明明方式设置,例如驼峰,中华线,首字母小写,首字母大写等
- @Transient 不序列化字段
2.3 注解使用示例
@Data
public class User<T> {
@JsonIgnore // 忽略序列化字段
private String pid;
@Transient // 不序列化字段
private String remark;
private Role role;
@JsonProperty("userName") //转换属性名称
private String account;
//反序列化--格式化日期
@JsonFormat(pattern="yyyy-MM-dd HH:mm:ss",timezone="GMT+8")
private LocalDateTime createTime;
//自定义序列化
@JsonSerialize(using = Date2LongSerialize.class)
private Date operaterTime;
//自定义反序列化处理
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date eventDate;
}
2.4、jackson和xml序列化与反序列化
//(15)xml的序列化
@Data
@JacksonXmlRootElement(localName = "root")
public class RootXml {
private String k1;
@JacksonXmlProperty(localName = "k-2")
private Integer k2;
@JacksonXmlElementWrapper(localName = "k3")
private Collection<String> ki;
@JacksonXmlElementWrapper(localName = "k4")
@JacksonXmlProperty(localName = "ka")
private Collection<String> k4;
@JacksonXmlElementWrapper(localName = "k5", useWrapping = false)
private Collection<String> k5;
@JacksonXmlProperty(isAttribute = true)
private Integer k6;
@Data
public static class Value1 {
@JacksonXmlText
private String a;
}
private Value1 k7;
@Data
public static class Value2 {
@JacksonXmlText(value = false)
private String a;
}
private Value2 k8;
@JacksonXmlCData(value = true) // 序列化时是否总是使用 CDATA 块
private String k9;
}
//反序列化
//ReqMessage reqMessage = JacksonUtil.readValueXml(json, RootXml.class);
4、各种自定义的示例
4.1、自定义序列化器示例
// Date自定义序列化
public class CustomDateSerializer extends StdSerializer<Date> {
private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() { this(null); }
public CustomDateSerializer(Class<Date> t) { super(t); }
@Override
public void serialize(Date value, JsonGenerator gen, SerializerProvider arg2)
throws IOException, JsonProcessingException {
gen.writeString(formatter.format(value));
}
}
// LocalDateTime 自定义序列化
public class MyLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
String dateStr = parser.getText();
DateTime dateTime = null;
try{
dateTime = DateUtil.parse(dateStr);
}catch (Exception e){
dateTime = DateUtil.parseDateTime(dateStr.replaceAll("T"," "));
}
LocalDateTime localDateTime = dateTime.toJdkDate().toInstant()
.atZone(ZoneId.systemDefault()).toLocalDateTime();
return localDateTime;
}
@Override
public Class<?> handledType() {
return LocalDateTime.class;
}
}
4.2 自定义反序列化器
// Date反序列化器
public class CustomDateDeserializer extends StdDeserializer<Date> {
private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
super(vc);
}
@Override
public Date deserialize(JsonParser jsonparser, DeserializationContext context) throws IOException {
String date = jsonparser.getText();
try {
return formatter.parse(date);
} catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
// LocalDateTime反序列化器
public class MyLocalDateTimeDeserializer extends JsonDeserializer<LocalDateTime> {
@Override
public LocalDateTime deserialize(JsonParser parser, DeserializationContext context) throws IOException {
String dateStr = parser.getText();
DateTime dateTime = null;
try{
dateTime = DateUtil.parse(dateStr);
}catch (Exception e){
dateTime = DateUtil.parseDateTime(dateStr.replaceAll("T"," "));
}
Date date = dateTime.toJdkDate();
Instant instant = date.toInstant();
ZoneId zoneId = ZoneId.systemDefault();
LocalDateTime localDateTime = instant.atZone(zoneId).toLocalDateTime();
return localDateTime;
}
@Override
public Class<?> handledType() {
return LocalDateTime.class;
}
}
4.2 自定义过滤器
FilterProvider filters = new SimpleFilterProvider().addFilter("myFilter",
SimpleBeanPropertyFilter.filterOutAllExcept("name"));
5、Jackson工具类
public class JacsonUtils {
public static final ObjectMapper MAPPER;
static {
MAPPER = new ObjectMapper();
MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL);
MAPPER.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"));
}
//===============================序列化================//
@SneakyThrows
public static String toString(Object obj) {
if (obj == null) return null;
if (obj.getClass() == String.class) return Convert.toStr(obj);
return MAPPER.writeValueAsString(obj);
}
//==========================反序列化===============//
//对象反序列化
@SneakyThrows(value={IOException.class})
public static <T> T toBean(String json, Class<T> tClass) {
if(StrUtil.isEmpty(json)) return null;
return MAPPER.readValue(json, tClass);
}
//集合反序列化
@SneakyThrows(value={IOException.class})
public static <E> List<E> toList(String json, Class<E> eClass) {
if(StrUtil.isEmpty(json)) return null;
JavaType javaType = MAPPER.getTypeFactory().constructParametricType(List.class, Bean.class);
return MAPPER.readValue(json,javaType);
}
//Map集合反序列化
@SneakyThrows(value={IOException.class})
public static <K, V> Map<K, V> toMap(String json, Class<K> kClass, Class<V> vClass) {
if(StrUtil.isEmpty(json)) return null;
JavaType javaType = MAPPER.getTypeFactory()
.constructParametricType(HashMap.class,String.class, Bean.class);
return MAPPER.readValue(json, javaType);
}
//复杂对象反序列化
@SneakyThrows(value={IOException.class})
public static <T> T nativeRead(String json, TypeReference<T> type) {
if(StrUtil.isEmpty(json)) return null;
return MAPPER.readValue(json, type);
}
}
二、fastJson方案
1、添加依赖
<!-- fastjson -->
<dependency>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
<version>2.0.1</version>
</dependency>
2、配置类
- 一般场景下可以不需要配置类,采用默认的方式即可
@Configuration
public class FJsonConfig {
@Bean
public HttpMessageConverter configureMessageConverters() {
FastJsonHttpMessageConverter converter = new FastJsonHttpMessageConverter();
FastJsonConfig config = new FastJsonConfig();
config.setSerializerFeatures(
// 可以配置不同的属性序列化方式
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullStringAsEmpty,
SerializerFeature.WriteNullNumberAsZero,
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteNullBooleanAsFalse,
SerializerFeature.DisableCircularReferenceDetect);
converter.setFastJsonConfig(config);
converter.setDefaultCharset(Charset.forName("UTF-8"));
List<MediaType> mediaTypeList = new ArrayList<>();
mediaTypeList.add(MediaType.APPLICATION_JSON);
converter.setSupportedMediaTypes(mediaTypeList);
return converter;
}
}
2、fastjson使用注解自定义序列化
- @JSONField(name = “AGE”)
- name 设置序列后别名
- format 格式化输出日期
- ordinal 输出排列顺序
- serialize 是否序列化输出
- deserialize 是否反序列化
@Data
public class Person {
@JSONField(name = "AGE")
private int age;
@JSONField(name = "FULL NAME")
private String fullName;
@JSONField(name="DATE OF BIRTH", format="dd/MM/yyyy", ordinal = 3)
private Date dateOfBirth;
@JSONField(name="CREATEDATE", serialize=false)
private Data createDate;
}
3、json工具类整理
调用时,可以直接使用fastJsonApi
- JSON 作为fastjson的json处理入口,相当于一个工具类,提供parseObject,parseArray,toJsonString,toJsonBytes等序列化和反序列化的
- JSONObject/JSONArray 解析后的对象或数组
- JSONPath采用path方式获取json值
- JSONReader json的读取器,
public class FastJsonUtil {
private static SerializeConfig config;
static {
config = new SerializeConfig();
config.put(Date.class, new SimpleDateFormatSerializer("yyyy-MM-dd HH:mm:ss"));
config.put(LocalDateTime.class, DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
}
//设置属性
private static final SerializerFeature[] features = {
SerializerFeature.WriteMapNullValue,
SerializerFeature.WriteNullListAsEmpty,
SerializerFeature.WriteNullNumberAsZero,
SerializerFeature.WriteNullBooleanAsFalse,
SerializerFeature.WriteNullStringAsEmpty
};
//=========================序列化==========================//
/** 对象转json */
public static String toJSON(Object object) {
if(object==null) return null;
return JSON.toJSONString(object, config, features);
}
//===================反序列化================================
/** Json 转为 Jave Bean */
public static <T> T toBean(String text, Class<T> clazz) {
if(StrUtil.isEmpty(text)) return null;
return JSON.parseObject(text, clazz);
}
/** json转对象数组 */
public static Object[] toArray(String text) {
if(StrUtil.isEmpty(text)) return null;
return toArray(text, null);
}
public static <T> Object[] toArray(String text, Class<T> clazz) {
if(StrUtil.isEmpty(text)) return null;
return JSON.parseArray(text, clazz).toArray();
}
public static Map<?, ?> toMap(String json) {
if(StrUtil.isEmpty(json)) return null;
return JSON.parseObject(json);
}
public static <T> List<T> toList(String text, Class<T> clazz) {
if(StrUtil.isEmpty(text)) return null;
return JSON.parseArray(text, clazz);
}
public static Object getValueFromJson(final String json, final String key) {
if(StrUtil.isEmpty(json)) return null;
return JSON.parseObject(json).getString(key);
}
}
三、GSON方案
添加依赖
<!-- 添加Gson依赖 -->
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>${gson.version}</version>
</dependency>
1、Gson注解Bean
- @SerializedName(value = “nameB”, alternate = {“nameC”, “nameD”})
- value 序列化别名
- alternate 发序列化的备用名
- @Expose(serialize = true, deserialize = false)
- serialize 是否可以序列化
- deserialize 是否可以反序列化
@Data
public class MyClass {
@SerializedName("nameA")
String a;
@SerializedName(value = "nameB", alternate = {"nameC", "nameD"})
String b;
@Expose(serialize = true, deserialize = false)
String c;
}
2、Gson工具类
@Configuration
@EnableWebMvc
public class GsonUtils extends WebMvcConfigurationSupport {
//无参的私有构造方法
private GsonUtils() { }
//不用创建对象,直接使用Gson.就可以调用方法
private static Gson gson = null;
//判断gson对象是否存在了,不存在则创建对象
static {
if (gson == null) {
//gson = new Gson();
gson= new GsonBuilder().setDateFormat("yyyy-MM-dd HH:mm:ss").create();
}
}
@Override
protected void extendMessageConverters(List<HttpMessageConverter<?>> converters) {
converters.removeIf(httpMessageConverter ->
httpMessageConverter instanceof MappingJackson2HttpMessageConverter);
converters.add(new GsonHttpMessageConverter());
super.extendMessageConverters(converters);
}
//==============================序列化======================//
public static String toString(Object object) {
if(gson==null) return null;
return gson.toJson(object);
}
//=============================反序列化===================//
@SneakyThrows
public static <T> T toBean(String gsonString, Class<T> cls) {
if(gson==null) return null;
return gson.fromJson(gsonString, cls);
}
@SneakyThrows
public static <T> List<T> toList(String gsonString, Class<T> cls) {
if(gson==null) return null;
return gson.fromJson(gsonString, new TypeToken<List<T>>() { }.getType());
}
@SneakyThrows
public static <T> List<T> toList2(String json, Class<T> cls) {
if(gson==null) return null;
ArrayList<T> mList = new ArrayList<T>();
JsonArray array = new JsonParser().parse(json).getAsJsonArray();
for(final JsonElement elem : array){
mList.add(gson.fromJson(elem, cls));
}
return mList;
}
@SneakyThrows
public static <T> List<Map<String, T>> toListMap(String gsonString) {
if(gson==null) return null;
return gson.fromJson(gsonString, new TypeToken<List<Map<String, T>>>() { }.getType());
}
@SneakyThrows
public static <T> Map<String, T> toMap(String gsonString) {
if(gson==null) return null;
return gson.fromJson(gsonString, new TypeToken<Map<String, T>>() { }.getType());
}
}
四、JsonPath工具
http://www.ibloger.net/article/2329.html
添加依赖
<!--json-path工具-->
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.2.0</version>
</dependency>
1、JSONPath的使用
- jsonpath主要就是通过类似地址的方式直接获取对象,目前不常用,fastjson有对应的功能
相关API使用
参照jsonpath语法
public class JsonFileUtil {
// 直接读取json
public static void readjson(String json,String jsonPath){
TypeRef<List<String>> typeRef = new TypeRef<List<String>>(){};
List<String> titles = JsonPath.parse(json).read("$.store.book[*].title", typeRef);
List<String> authors = JsonPath.read(json, "$.store.book[*].author",typeRef);
Date date = JsonPath.parse(json1).read("$['date_as_long']", Date.class);
Book book = JsonPath.parse(json).read("$.store.book[0]", Book.class);
}
//通过Configuration读取并解析文件,获取某个值,可以多次获取
public static void readConfiguration(){
Object document = Configuration.defaultConfiguration().jsonProvider().parse(json);
String author0 = JsonPath.read(document, "$.store.book[0].author");
}
public static void readContext(){
ReadContext ctx = JsonPath.parse(json);
List<String> authorsOfBooksWithISBN = ctx.read("$.store.book[?(@.isbn)].author");
Configuration configuration = Configuration.defaultConfiguration();
List<Map<String, Object>> expensiveBooks = JsonPath
.using(configuration)
.parse(json)
.read("$.store.book[?(@.price > 10)]", List.class);
}
//支持语法
public static void readfilter(){
List<Map<String, Object>> books = JsonPath.parse(json).read("$.store.book[?(@.price < 10)]");
//过滤
Filter cheapFictionFilter = Filter.filter(
Criteria.where("category").is("fiction").and("price").lte(10D)
);
List<Map<String, Object>> books1 = JsonPath.parse(json).read("$.store.book[?]", cheapFictionFilter);
}
}
https://www.cnblogs.com/baiqiantao/p/7512336.html