Лучший парсер JSON для Java — FasterXML/jackson

JSON

Стандартная библиотека JSON для Java (или платформа JVM), также известная как «лучший анализатор JSON для Java».

Джексон предоставляет набор инструментов обработки данных для Java (и платформы JVM), включая флагманскую потоковую библиотеку парсера/генератора JSON, соответствующую библиотеку привязки данных (POJO в JSON и обратно) и дополнительные модули формата данных. Обработка данных, закодированных в Avro, BSON, CBOR, CSV, Smile, (Java)Properties, Protobuf, XML или YAML; существует даже большое количество модулей формата данных для поддержки типов данных для широко используемых типов данных, таких как Guava, Joda, Коллекции ПК и т. д.

Фактические основные компоненты находятся в рамках собственного проекта, включая два основных пакета: джексон-кор, Джексон-привязка данных.

Проект jackson-core содержит абстрактные базовые синтаксические анализаторы и генераторы потоковой передачи, используемые обработчиками данных Jackson, а также стандартные реализации синтаксических анализаторов и генераторов для обработки формата JSON. jackson-databind содержит общие функции привязки данных и древовидные модели для процессоров данных Jackson. Он построен на пакете StreamingAPI (парсер потоков, генератор) и настроен с использованием аннотаций Джексона.

1 Streaming API Core Streaming API

Streaming 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();

2 Привязка данных

Пакет 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);

3 Модель дерева

После вызова апи необходимо разобрать возвращаемые json данные для получения информации, в этом случае создавать соответствующий класс для json очень неудобно. В настоящее время более удобно использовать древовидную модель для разбора 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;
        }
    }
}

4 Преобразование типов

Полезной (но не очень известной) особенностью Jackson является его способность выполнять произвольные преобразования POJO в POJO. Как правило, сначала запишите POJO как JSON, а затем привяжите JSON к другому POJO. Реализация Джексона пропускает фактическое создание 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);

5 общих аннотаций и конфигураций

1. Общие примечания:
@JsonIgnore Эта аннотация используется для свойств, чтобы игнорировать свойство при выполнении операций JSON.
@JsonFormat Эта аннотация используется в свойствах для прямого преобразования типа Date в нужный формат, например @JsonFormat(шаблон = «гггг-ММ-дд ЧЧ-мм-сс»).
@JsonProperty Эта аннотация используется в свойствах для сериализации имени свойства в другое имя, например сериализации свойства trueName в имя, @JsonProperty("name"). Вы также можете добавить аннотацию @JsonIgnoreProperties({ "a", "b" }) непосредственно в класс, чтобы пропустить свойства a и b.
Конструкторы @JsonCreator могут быть публичными или приватными. Джексону не нужно определять «конструктор по умолчанию» (конструктор, не принимающий параметров).

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);

6 Использование Джексона в SpringBoot

Встроенный синтаксический анализатор json в SpringMVC — это 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 не очень удобно. Надеюсь, эта статья будет вам полезна. Приветствую всех, чтобы учиться вместе, пожалуйста, поправьте меня, если есть какие-либо ошибки.