Java(或JVM平台)的标准JSON库,或者被称为“ Java的最佳JSON解析器”。
Jackson提供了一套用于Java(和JVM平台)的数据处理工具,包括旗舰级流JSON解析器/生成器库,匹配的数据绑定库(与JSON之间的POJO)和附加的数据格式模块。以Avro, BSON, CBOR, CSV, Smile, (Java)Properties, Protobuf, XML 或YAML编码的处理数据 ; 甚至还有大量的数据格式模块,以支持广泛使用的数据类型的数据类型,例如 Guava, Joda, PCollections 等等。
实际的核心组件位于他们自己的项目下-包括两个核心软件包: jackson-core、 jackson-databind。
jackson-core项目包含Jackson数据处理器使用的抽象核心流式解析器和生成器,还包括处理JSON格式的解析器、生成器的默认实现。jackson-databind包含用于Jackson数据处理器的通用数据绑定功能和树模型。它基于StreamingAPI(流解析器、生成器)包构建,并使用Jackson注释进行配置。
流式API是一套比较底层的API,速度快,但是使用起来特别麻烦。它主要是有两个核心类,一个是JsonGenerator,用来生成json,另一个是JsonParser,用来读取json内容。
使用通常从创建可重用(并且在配置后是线程安全的)JsonFactory实例开始:
JsonFactory factory = new JsonFactory(); // 配置(如有必要): factory.enable(JsonParser.Feature.ALLOW_COMMENTS); // 另外,您也可以方便地ObjectMapper(从Jackson-Databind软件包中获得)。如果是这样,您可以执行以下操作: JsonFactory factory = objectMapper.getFactory(); 复制代码
官方使用示例: Reading and Writing Event Streams
JsonFactory f = mapper.getFactory(); // 也可以直接构造 JsonFactory factory = new JsonFactory(); // 首先写入 File jsonFile = new File("test.json"); JsonGenerator g = f.createGenerator(jsonFile); // 写入 JSON: { "message" : "Hello world!" } g.writeStartObject(); g.writeStringField("message", "Hello world!"); g.writeEndObject(); g.close(); // 然后读取 JsonParser p = f.createParser(jsonFile); JsonToken t = p.nextToken(); t = p.nextToken(); if ((t != JsonToken.FIELD_NAME) || !"message".equals(p.getCurrentName())) { // handle error } t = p.nextToken(); if (t != JsonToken.VALUE_STRING) { // similarly } String msg = p.getText(); System.out.printf("My message to you is: %s!/n", msg); p.close(); 复制代码
jackson-databind软件包依赖于jackson-core和jackson-annotations软件包,但是当使用Maven或Gradle之类的构建工具时,依赖项会自动包括在内。基本使用:
//创建一个com.fasterxml.jackson.databind.ObjectMapper用于所有数据绑定的实例,ObjectMapper是线程安全的,应该尽量的重用。 ObjectMapper mapper = new ObjectMapper(); // 字符串反序列化为对象 Grade grade = mapper.readValue(jsonStr, Grade.class); // Jackson是基于JavaBean来序列化属性的,属性要有GETTER方法,才会输出该属性 Map<String, ResultValue> results = mapper.readValue(jsonSource, new TypeReference<Map<String, ResultValue>>() { } ); // 对象序列号化为json字符串 String gradeStr = mapper.writeValueAsString(grade); // 对象序列号化为byte数组 byte[] jsonBytes = mapper.writeValueAsBytes(grade); // 写入文件 mapper.writeValue(new File("result.json"), grade); 复制代码
在调用了某个api后,需要解析返回的json数据获取信息,这种情况下为json创建一个对应的类是很不方便的。此时使用Tree Model来解析json就比较方便了
JsonNode root = mapper.readTree(rerenjson); JsonNode user = root.get("user"); root.with("other").put("type", "student"); int id = user.get("id").asInt(); String name = user.get("name").asText(); JsonNode avators = user.get("avatar"); if (avators.isArray()) { for (Iterator it = avators.getElements(); it.hasNext(); ){ JsonNode avator = it.next(); if ("tiny".equals(avator.get("type").asText())) { String ava = avator.get("url").asText(); break; } } } 复制代码
Jackson的一项有用(但不是很广为人知)的功能是它能够进行任意的POJO到POJO转换。一般做法,首先将POJO编写为JSON,其次将JSON绑定到另一种POJO中。Jackson实现跳过JSON的实际生成,并使用更高效的中间实现。
// 基本使用 ResultType result = mapper.convertValue(sourceObject, ResultType.class); // List<Integer> 转 int[] List<Integer> sourceList = ...; int[] ints = mapper.convertValue(sourceList, int[].class); // POJO 转 Map! Map<String,Object> propertyMap = mapper.convertValue(pojoValue, Map.class); // POJO 转 back PojoType pojo = mapper.convertValue(propertyMap, PojoType.class); // 解码Base64!(缺省字节[]表示是base64编码字串) String base64 = "TWFuIGlzIGRpc3Rpbmd1aXNoZWQsIG5vdCBvbmx5IGJ5IGhpcyByZWFzb24sIGJ1dCBieSB0aGlz"; byte[] binary = mapper.convertValue(base64, byte[].class); 复制代码
1、常用注解:
@JsonIgnore 此注解用于属性上,作用是进行JSON操作时忽略该属性。
@JsonFormat 此注解用于属性上,作用是把Date类型直接转化为想要的格式,如@JsonFormat(pattern = “yyyy-MM-dd HH-mm-ss”)。
@JsonProperty 此注解用于属性上,作用是把该属性的名称序列化为另外一个名称,如把trueName属性序列化为name,@JsonProperty(“name”)。也可以直接在类上添加注解 @JsonIgnoreProperties({ "a", "b" }),跳过a、b属性。
@JsonCreator构造函数可以是公共的,也可以是私有的。Jackson不需要定义“默认构造函数”(不带参数的构造函数)。
2、Mapper的一些实用配置:(其他配置可见上述jackson-databind官方链接)
// (空对象是否抛出异常) mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS); // (日期改为时间戳) mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS); // (特殊字符和打印符,这在FastJson曾是个bug) mapper.configure(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES, true); // (单引号) mapper.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true); 复制代码
SpringMVC内置json解析器就是Jackson,以SpringBoot技术栈开发的话,用默认的Jackson是最好的。
spring: jackson: # 设置属性命名策略,对应jackson下PropertyNamingStrategy中的常量值,SNAKE_CASE-返回的json驼峰式转下划线,json body下划线传到后端自动转驼峰式 property-naming-strategy: SNAKE_CASE # 全局设置@JsonFormat的格式pattern date-format: yyyy-MM-dd HH:mm:ss # 当地时区 locale: zh # 设置全局时区 time-zone: GMT+8 # 常用,全局设置pojo或被@JsonInclude注解的属性的序列化方式 default-property-inclusion: NON_NULL #不为空的属性才会序列化,具体属性可看JsonInclude.Include # 常规默认,枚举类SerializationFeature中的枚举属性为key,值为boolean设置jackson序列化特性,具体key请看SerializationFeature源码 serialization: WRITE_DATES_AS_TIMESTAMPS: true # 返回的java.util.date转换成timestamp FAIL_ON_EMPTY_BEANS: true # 对象为空时是否报错,默认true # 枚举类DeserializationFeature中的枚举属性为key,值为boolean设置jackson反序列化特性,具体key请看DeserializationFeature源码 deserialization: # 常用,json中含pojo不存在属性时是否失败报错,默认true FAIL_ON_UNKNOWN_PROPERTIES: false # 枚举类MapperFeature中的枚举属性为key,值为boolean设置jackson ObjectMapper特性 # ObjectMapper在jackson中负责json的读写、json与pojo的互转、json tree的互转,具体特性请看MapperFeature,常规默认即可 mapper: # 使用getter取代setter探测属性,如类中含getName()但不包含name属性与setName(),传输的vo json格式模板中依旧含name属性 USE_GETTERS_AS_SETTERS: true #默认false # 枚举类JsonParser.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonParser特性 # JsonParser在jackson中负责json内容的读取,具体特性请看JsonParser.Feature,一般无需设置默认即可 parser: ALLOW_SINGLE_QUOTES: true # 是否允许出现单引号,默认false # 枚举类JsonGenerator.Feature枚举类中的枚举属性为key,值为boolean设置jackson JsonGenerator特性,一般无需设置默认即可 # JsonGenerator在jackson中负责编写json内容,具体特性请看JsonGenerator.Feature 复制代码
默认配置(配置文件配置JacksonAutoConfiguration)和用户自定义Java代码配置只需要一种即可。
jackson
jackson-core
jackson-databind
平时我们使用最多的就是数据绑定吧,配置好之后真让人省心,树模型和类型转换也能为我们的工作带来便利,流式API日常使用不是太方便。希望这篇文章能对你们有帮助。欢迎大家一起学习,有误之处烦请大家指正。