Помимо FastJson, вы также должны знать о Джексоне (1)

Java

В конце прошлого месяца я получил сообщение об уязвимости безопасности в fastjson, и вдруг подумал, что таких инцидентов было много (на fastjson). Что касается безопасности, хотя вероятность того, что вас застрелят, невелика, в эту эпоху все более сложной информации безопасность становится все более и более важной.Так же, как рождение DevSecOps, нам также необходимо уделять внимание всему потоку создания ценности доставки программного обеспечения. безопасность в этом плане. Конечно, мы не будем сейчас говорить о плюсах и минусах FastJson, потому что наша цель в этой статье — дать всем понять и освоить Джексона.


Обзор

Jackson — очень популярная и эффективная библиотека на основе Java, которая может сериализовать объекты Java или отображать объекты Java в JSON и наоборот. Конечно, помимо Джексона, в Java есть много отличных однотипных библиотек, таких как:

Нет четкого ответа, какой из них лучше или какой из них наиболее популярен. Существует много типов технологий, и у всех разное отношение к разным технологиям. Ближе к дому статья в основном обсуждает Джексона. В этой статье в основном объясняются две наиболее распространенные операции, с которыми мы имеем дело в Json:

  • Сериализация объектов Java в JSON
  • Десериализовать строку JSON в объект Java

импортировать зависимости

Поскольку многие компоненты в Spring/SpringBoot уже поставляются с библиотекой Jackson, во многих случаях нет необходимости вручную вводить зависимости Jackson.

Вручную импортировать зависимости:

<dependency> 
  <groupId>com.fasterxml.jackson.core</groupId> 
  <artifactId>jackson-databind</artifactId> 
  <version>2.9.8</version>
</dependency>

Эта зависимость также транзитивно добавит в путь к классам следующие библиотеки:

  1. jackson-annotations-2.9.8.jar
  2. jackson-core-2.9.8.jar
  3. jackson-databind-2.9.8.jar

JavaObject to Json

ObjectMapper

ObjectMapper — это средство сопоставления (или средство связывания данных или кодек), которое предоставляет функциональные возможности для преобразования между объектами Java (экземплярами bean-компонентов) и JSON.

Сначала определите простой класс Java

public class Car {
    private String color;
    private String type;
    // standard getters setters
}

Преобразование объектов Java в Json

Мы используем ObjectMapperwriteValueСвязанный API для сериализации объектов Java

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("blue","c1");
System.out.println(objectMapper.writeValueAsString(car));

вывод в это время

{"color":"blue","type":"c1"}

Более

ObjectMapperwriteValueСвязанные API также предоставляют множество удобных методов сериализации Json, таких как: сериализация объектов в массивы байтов Json.writeValueAsBytes()метод, настраиваемый источник выводаwriteValue()метод...

ObjectMapper objectMapper = new ObjectMapper();
Car car = new Car("blue","c1");
objectMapper.writeValue(new File("./xxx.txt"),car);

Запустив приведенный выше код, сериализованный Json объекта Java будет выведен в файл xxx.txt.

image-20200605232424859


Json to JavaObject

Преобразование строки Json в объект Java

ObjectMapper objectMapper = new ObjectMapper();
String json = "{\"color\":\"blue\",\"type\":\"c1\"}";
Car car = objectMapper.readValue(json, Car.class);

Метод readValue() также принимает другие формы ввода, например файлы, содержащие строки JSON:

ObjectMapper objectMapper = new ObjectMapper();
Car car = objectMapper.readValue(new File("./xxx.txt"), Car.class);
System.out.println(car);

JSON to Jackson JsonNode

JsonNode

JSON можно преобразовать в объект JsonNode для извлечения данных из определенного узла.

Используя метод readTree(), мы можем преобразовать строку Json в JsonNode.

ObjectMapper objectMapper = new ObjectMapper();
String json = "{ \"color\" : \"Black\", \"type\" : \"FIAT\" }";
JsonNode jsonNode = objectMapper.readTree(json);
System.out.println(jsonNode.findValue("type").asText());
// 打印出“FAIT”

JSONArrayString to JavaList

ObjectMapper objectMapper = new ObjectMapper();
String jsonCarArray =
    "[{ \"color\" : \"Black\", \"type\" : \"BMW\" }, { \"color\" : 3. \"Red\", \"type\" : \"FIAT\" }]";
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>() {});

JSONString to JavaMap

ObjectMapper objectMapper = new ObjectMapper();
String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\" }";
Map<String, Object> map = objectMapper.readValue(json, new TypeReference<Map<String, Object>>() {
});

💡:Одним из самых больших преимуществ библиотеки Джексона является настраиваемый процесс сериализации и десериализации. Далее мы представим некоторыеРасширенные возможности, где входной или выходной ответ JSON может отличаться от объекта, который создает или использует ответ.

Настройка свойств сериализации и десериализации

String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" :\"1970\" }";

Предполагая, что указанная выше строка json используется для десериализации в объект Java, процесс синтаксического анализа по умолчанию приведет к исключению UnrecognizedPropertyException, поскольку есть новое поле year, которое не включено в класс Car.

Решите эту проблему, настроив свойства сериализации и десериализации:

ObjectMapper objectMapper = new ObjectMapper();
String jsonString = "{ \"color\" : \"Black\", \"type\" : \"Fiat\", \"year\" :\"1970\" }";
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
Car car = objectMapper.readValue(jsonString, Car.class);

Как и выше, мы настроили в ObjectMapperDeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES=false, так что новое поле игнорируется.

**Похоже:** Другой вариантFAIL_ON_NULL_FOR_PRIMITIVES, который определяет, разрешены ли нулевые значения для примитивных значений;FAIL_ON_NUMBERS_FOR_ENUMКонтролирует, разрешено ли сериализовать/десериализовать значения перечисления как числа...


пользовательский сериализатор или десериализатор

пользовательский сериализатор

public static class CustomCarSerializer extends StdSerializer<Car> {
    public CustomCarSerializer() {
        this(null);
    }

    public CustomCarSerializer(Class<Car> t) {
        super(t);
    }

    @Override
    public void serialize(Car car, JsonGenerator jsonGenerator, SerializerProvider serializer) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("car_brand", car.getType());
        jsonGenerator.writeEndObject();
    }
}

Как и выше, наследуя класс StdSerializer, мы реализуем собственный сериализатор.

Используйте пользовательский сериализатор:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("CustomCarSerializer", new Version(1, 0, 0, null, null, null));
module.addSerializer(Car.class, new CustomCarSerializer());
mapper.registerModule(module);
Car car = new Car("yellow", "enault");
System.out.println(mapper.writeValueAsString(car));
//输出{"car_brand":"enault"}

пользовательский десериализатор

public static class CustomCarDeserializer extends StdDeserializer<Car> {

        public CustomCarDeserializer() {
            this(null);
        }

        protected CustomCarDeserializer(Class<?> vc) {
            super(vc);
        }

        @Override
        public Car deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            Car car = new Car();
            ObjectCodec codec = p.getCodec();
            JsonNode node = codec.readTree(p);
            // try catch block
            JsonNode colorNode = node.get("color");
            String color = colorNode.asText();
            car.setColor(color);
            return car;
        }
    }

Как и выше, наследуя класс StdDeserializer, мы реализуем собственный сериализатор.

Используйте пользовательский десериализатор:

String json = "{ \"color\" : \"Black\", \"type\" : \"BMW\"}";
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("CustomCarDeserializer", new Version(1, 0, 0, null, null, null));
module.addDeserializer(Car.class, new CustomCarDeserializer());
mapper.registerModule(module);
Car car = mapper.readValue(json, Car.class);
//此时的car {color='Black', type='null'}

Формат времени обработки

⚠️: здесь показана только обработка LocalDate&LocalDateTime для Java8

Сначала создайте класс Car с полем даты и времени.

public class Car {
    private String color;
    private String type;
  	@JsonFormat(pattern = "yyyy-MM-dd")
    private LocalDateTime produceTime;
    // standard getters setters
}

Обработка пользовательского формата времени

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
Car car = new Car().setColor("blue").setType("c1").setProduceTime(LocalDateTime.now());
String carAsString = objectMapper.writeValueAsString(car);
System.out.println(carAsString);
//此时输出:{"color":"blue","type":"c1","produceTime":"2020-06-06"}

Работа с коллекциями

Еще одна небольшая, но полезная функция, предоставляемая классом DeserializationFeature, — это возможность генерировать нужный тип коллекции из ответа массива JSON.

String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\"}, { \"color\" : \"Red\", \"type\" : \"FIAT\"}]";
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(DeserializationFeature.USE_JAVA_ARRAY_FOR_JSON_ARRAY, true);
Car[] cars = objectMapper.readValue(jsonCarArray, Car[].class);

Как и выше, мы преобразовали строку JsonArray в массив объектов.

Мы также можем преобразовать его в коллекцию:

String jsonCarArray = "[{ \"color\" : \"Black\", \"type\" : \"BMW\"}, { \"color\" : \"Red\", \"type\" : \"FIAT\"}]";
ObjectMapper objectMapper = new ObjectMapper();
List<Car> listCar = objectMapper.readValue(jsonCarArray, new TypeReference<List<Car>>(){});

Суммировать

Jackson — это надежная и зрелая библиотека сериализации/десериализации JSON для Java. API ObjectMapper предоставляет простой способ анализа и создания объектов ответа JSON с большой гибкостью.


🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟🌟

Добро пожаловать в блог автора:blog.dongxishaonian.tech

Подписывайтесь на официальный аккаунт автора и публикуйте различные оригинальные/качественные технические статьи ⬇️

WechatIMG6