StringBoot之jackson

Spring Boot 内置了jackson来完成JSON的序列化和反序列化操作。Jackson使用ObjectMapper类将POJO对象序列化成JSON字符串,也能将JSON字符串反序列化成POJO对象。

JackSon支持三种层次的序列化和反序列化方式:

  • 采用JsonParser来解析JSON,解析结果是一串Tokens,采用JsonGenerator来生成JSON,这是最底层的方式。
  • 采用树遍历方式,JSON被读入到JsonNode对象中,可以像操作XML DOM那样读取JSON。
  • 采用DataBind方式,将POJO序列化成JSON,或者反序列化到POJO,这是最直接和最简单的一种方式,不过有时候需要辅助Jackson的注解或者上述序列化实现类来个性化序列化和反序列化操作。

1、jackson全局配置

方式一:

# jackson全局配置jackson:# 全局设置@JsonFormat的格式patterndate-format: yyyy-MM-dd HH:mm:ss# 当地时区locale: zh# 设置全局时区time-zone: GMT+8serialization:#格式化输出indent_output: true
#      #忽略无法转换的对象
#      fail_on_empty_beans: false
#    deserialization:
#      #允许对象忽略json中不存在的属性
#      fail_on_unknown_properties: falseparser:#允许出现特殊字符和转义符allow_unquoted_control_chars: true#允许出现单引号allow_single_quotes: true
#    #如果加该注解的字段为null,那么就不序列化这个字段了
#    default-property-inclusion: NON_EMPTY

方式二:

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.http.converter.json.Jackson2ObjectMapperBuilder;
import java.io.IOException;@Configuration
public class JacksonConfig {/*** 重新注入ObjectMapper* 注:使用此方式ObjectMapper,application中Jackson自动失效** @param builder* @return*/@Bean@Primary@ConditionalOnMissingBean(ObjectMapper.class)public ObjectMapper jacksonObjectMapper(Jackson2ObjectMapperBuilder builder) {ObjectMapper objectMapper = builder.createXmlMapper(false).build();// 通过该方法对mapper对象进行设置,所有序列化的对象都将按改规则进行系列化// Include.Include.ALWAYS 默认// Include.NON_DEFAULT 属性为默认值不序列化// Include.NON_EMPTY 属性为 空("") 或者为 NULL 都不序列化,则返回的json是没有这个字段的。这样对移动端会更省流量// Include.NON_NULL 属性为NULL 不序列化objectMapper.setSerializationInclusion(JsonInclude.Include.NON_EMPTY);// 反序列化时 忽略匹配不到的属性字段objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);// 允许出现单引号objectMapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);// 字段保留,将null值转为""objectMapper.getSerializerProvider().setNullValueSerializer(new JsonSerializer<Object>() {@Overridepublic void serialize(Object o, JsonGenerator jsonGenerator,SerializerProvider serializerProvider)throws IOException {jsonGenerator.writeString("");}});return objectMapper;}
}

注:两个一起配置方法二生效

2、Java对象与JSON数据转换

使用ObjectMapper的readValue来实现,我们现在举个例子,可以创建一个POJO对象来与JSON相对应,POJO类如下:

public class User {Long id;String name;public Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}

(1)使用readValue方法来反序列化上面的JSON字符串,即json转换为对象:

@Autowired
private ObjectMapper mapper;	@GetMapping("/dataBind.json")
public @ResponseBody String dataBind() throws IOException{String json = "{"name":"lijz","id":10}";User user = mapper.readValue(json, User.class);return "name:"+user.getName()+",id:"+user.getId();
}

(2)将POJO序列化成JSON,使用mapper的writeValueAsString方法:

@Autowired
private ObjectMapper mapper;	@GetMapping("/serialization.json")
public @ResponseBody String dataBind() throws IOException{User user = new User();user.setName("scg");user.setId((long) 18);String jsonStr = mapper.writeValueAsString(user);return jsonStr;
}

(3)json转集合

json转集合比较麻烦,因为你无法同时把集合的class和元素的class同时传递到一个参数。因此Jackson做了一个类型工厂,用来解决这个问题:

// json处理工具
private ObjectMapper mapper = new ObjectMapper();
@Test
public void testJson() throws IOException {User user = new User();user.setId(8L);user.setAge(21);user.setName("柳岩");user.setUserName("liuyan");// 序列化,得到对象集合的json字符串String json = mapper.writeValueAsString(Arrays.asList(user, user));// 反序列化,接收两个参数:json数据,反序列化的目标类字节码List<User> users = mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, User.class));for (User u : users) {System.out.println("u = " + u);}
}

(4)json转任意复杂类型

当对象泛型关系复杂时,类型工厂也不好使了。这个时候Jackson提供了TypeReference来接收类型泛型,然后底层通过反射来获取泛型上的具体类型。实现数据转换。

// json处理工具
private ObjectMapper mapper = new ObjectMapper();
@Test
public void testJson() throws IOException {User user = new User();user.setId(8L);user.setAge(21);user.setName("柳岩");user.setUserName("liuyan");// 序列化,得到对象集合的json字符串String json = mapper.writeValueAsString(Arrays.asList(user, user));// 反序列化,接收两个参数:json数据,反序列化的目标类字节码List<User> users = mapper.readValue(json, new TypeReference<List<User>>(){});for (User u : users) {System.out.println("u = " + u);}
}

3、Jackson 注解

Jackson包含了很多注解,用来个性化序列化和反序列化操作,主要有如下注解。

(1)@JsonProperty,作用在属性上,用来为JSON Key指定一个别名。

@JsonProperty("userName")
private String name;

(2)@JsonIgnore,作用在属性上,用来忽略此属性。

@JsonIgnore
private String age;

(3)@JsonIgnoreProperties,忽略一组属性,作用于类上

@JsonIgnoreProperties({"id","photo"})
public class User {}

(4)@JsonFormat,用于日期格式化。

一般与@DateTimeFormat配合使用,@DateTimeFormat(pattern = “yyyy-MM-dd HH-mm-ss”)是用于指定前端传过来的格式

@JsonFormat(timezone = "GMT+8", pattern = "yyyy-MM-dd HH-mm-ss")
private Date d;

(5)@JsonView,作用在类或者属性上,用来定义一个序列化组。

Spring MVC的Controller方法可以使用同样的@JsonView来序列化属于这一组的配置。比如对于User对象,某些情况下只返回id属性就行,而某些情况下需要返回id和名称。代码如下:

public class User {public interface IdView{};public interface IdNameView extends IdView{};@JsonView(IdView.class)private Integer id;@JsonView(IdNameView.class)private String name;public Integer getId() {return id;}public void setId(Integer id) {this.id = id;}public String getName() {return name;}public void setName(String name) {this.name = name;}
}
/**
* controller*/
@JsonView(User.IdView.class)
@RequestMapping("/id.json")
public @ResponseBody User queryIds(){User user = new User();user.setId(1);user.setName("scg");return user;
}

(6)@JsonSerialize,指定一个实现类来自定义序列化。类必须实现JsonSerializer接口。

  1. 写一个负责转换的类,里面写好规则
public class MySerializerUtils extends JsonSerializer<Integer> {@Overridepublic void serialize(Integer status, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException, JsonProcessingException {String statusStr = "";switch (status) {case 0:statusStr = "新建状态";break;case 1:statusStr = "就绪状态";break;case 2:statusStr = "运行状态";break;case 3:statusStr = "阻塞和唤醒线程";break;case 4:statusStr = " 死亡状态";break;default:statusStr = "状态信息不符合";}jsonGenerator.writeString(statusStr);}}
  1. 在实体类上需要装换的字段上加上注解
/*** 多线程生命周期状态值*/
@JsonSerialize(using = MySerializerUtils.class)
private int status;

注:@JsonSerialize注解,主要应用于数据转换,该注解作用在该属性的getter()方法上。

4、jack工具类

(1)引入相关包

    org.springframework.bootspring-boot-starter-loggingcom.fasterxml.jackson.corejackson-databind2.9.6compile

(2)jack工具类

package cn.jun.common.utils;import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.ObjectMapper;import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
//Nullable需要引入spring-web包
import org.springframework.lang.Nullable;import java.io.IOException;
import java.util.List;
import java.util.Map;/*** jack处理json相关的工具类* @create: 2021-09-10 10:20**/@Slf4j
public class JsonUtils {public static final ObjectMapper mapper = new ObjectMapper();/*** 对象转换为json字符串* @param obj* @return*/@Nullablepublic static String toString(Object obj) {if (obj == null) {return null;}if (obj.getClass() == String.class) {return (String) obj;}try {return mapper.writeValueAsString(obj);} catch (JsonProcessingException e) {log.error("json序列化出错:" + obj, e);return null;}}@Nullablepublic static <T> T toBean(String json, Class<T> tClass) {try {return mapper.readValue(json, tClass);} catch (IOException e) {log.error("json解析出错:" + json, e);return null;}}@Nullablepublic static <E> List<E> toList(String json, Class<E> eClass) {try {return mapper.readValue(json, mapper.getTypeFactory().constructCollectionType(List.class, eClass));} catch (IOException e) {log.error("json解析出错:" + json, e);return null;}}@Nullablepublic static <K, V> Map<K, V> toMap(String json, Class<K> kClass, Class<V> vClass) {try {return mapper.readValue(json, mapper.getTypeFactory().constructMapType(Map.class, kClass, vClass));} catch (IOException e) {log.error("json解析出错:" + json, e);return null;}}@Nullablepublic static <T> T nativeRead(String json, TypeReference<T> type) {try {return mapper.readValue(json, type);} catch (IOException e) {log.error("json解析出错:" + json, e);return null;}}@Data@AllArgsConstructor@NoArgsConstructorclass User{private String name;private Integer age;}public static void main(String[] args) {String json="{\"namge\":\"zhuxinjun\",\"age\":\"21\"}";Map<String, String> map = toMap(json, String.class, String.class);System.out.println("map:"+map);String j="[{\"namge\":\"zhuxinjun\",\"age\":\"21\"},{\"namge\":\"yangyang\",\"age\":\"32\"}]";List<Map<String, String>> maps = nativeRead(j, new TypeReference<List<Map<String, String>>>() {});for(Map<String,String> map1:maps){System.out.println("map1"+map1);}}
}

5、ObjectMapper对象和JsonNode对象

ObjectMapper可以让对象与JSON之间相互转换,除此之外Jackson还提供了JsonGenerator 和JsonParser 这两个类,它们可以更细粒度化。调用ObjectMapper的writeValueAsString()和readValue()方法,最终还是会交给JsonGenerator和JsonParser去处理。

ObjectMapper类是Jackson库的主要类。Jackson ObjectMapper可以从字符串、流或文件中解析JSON,并创建表示解析JSON的Java对象或对象图。将JSON解析为Java对象也被称为从JSON反序列化Java对象。Jackson ObjectMapper还可以从Java对象创建JSON。从Java对象生成JSON也被称为将Java对象序列化成JSON。Jackson对象映射器可以将JSON解析为由您开发的类的对象,或者为内置JSON树模型的对象中。

【ObjectMapper对象构造函数说明】
(1)ObjectMapper()无参构造函数:默认的构造函数,这将构建默认JsonFactory必要时使用StdSerializerProvider作为其SerializerProvider,并BeanSerializerFactory作为其SerializerFactory。
(2)ObjectMapper(JsonFactory jf)构造函数:构造使用指定的JsonFactory构建必要的JsonParsers和/或JsonGenerators映射。
(3)ObjectMapper(JsonFactory jf, SerializerProvider sp, DeserializerProvider dp)
(4)ObjectMapper(JsonFactory jf, SerializerProvider sp, DeserializerProvider dp, SerializationConfig sconfig, DeserializationConfig dconfig)
(5)ObjectMapper(SerializerFactory sf) 不推荐使用。使用其他构造来代替; 注意,可以设置序列化工厂。
JsonNode对象就是JackJson的树模型,ObjectMapper构建JsonNode节点树。这是最灵活的方法。它类似于DOM解析器的XML。

6、FastJson替换jackson

import com.alibaba.fastjson.serializer.SerializerFeature;
import com.alibaba.fastjson.support.config.FastJsonConfig;
import com.alibaba.fastjson.support.spring.FastJsonHttpMessageConverter;
import org.springframework.boot.autoconfigure.web.HttpMessageConverters;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.converter.HttpMessageConverter;import java.nio.charset.Charset;@Configuration
public class HttpMessageConverterConfig {//引入Fastjson解析json,不使用默认的jackson//必须在pom.xml引入fastjson的jar包,并且版必须大于1.2.10@Beanpublic HttpMessageConverters fastJsonHttpMessageConverters() {//1、定义一个convert转换消息的对象FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();//2、添加fastjson的配置信息FastJsonConfig fastJsonConfig = new FastJsonConfig();SerializerFeature[] serializerFeatures = new SerializerFeature[]{//    输出key是包含双引号
//                SerializerFeature.QuoteFieldNames,//    是否输出为null的字段,若为null 则显示该字段
//                SerializerFeature.WriteMapNullValue,//    数值字段如果为null,则输出为0SerializerFeature.WriteNullNumberAsZero,//     List字段如果为null,输出为[],而非nullSerializerFeature.WriteNullListAsEmpty,//    字符类型字段如果为null,输出为"",而非nullSerializerFeature.WriteNullStringAsEmpty,//    Boolean字段如果为null,输出为false,而非nullSerializerFeature.WriteNullBooleanAsFalse,//    Date的日期转换器SerializerFeature.WriteDateUseDateFormat,//    循环引用SerializerFeature.DisableCircularReferenceDetect,};fastJsonConfig.setSerializerFeatures(serializerFeatures);fastJsonConfig.setCharset(Charset.forName("UTF-8"));//3、在convert中添加配置信息fastConverter.setFastJsonConfig(fastJsonConfig);//4、将convert添加到converters中HttpMessageConverter<?> converter = fastConverter;return new HttpMessageConverters(converter);}
}


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部