Я вижу, что многие люди до сих пор не знают о возможностях этой библиотеки, даже если вы уже используете ее в некоторых разработках, не изучили все ее содержимое, думая об этом, я собрал эту статью, чтобы представить вам основные функции Jackson, которые очень помогут вам в манипуляции JSON на Java, когда мы говорим о REST с Java/Spring…. невозможно не думать о том, что Jackson обрабатывает входные и выходные данные нашего сервиса, а также других API, которые мы потребляем внутри компании.
Jackson Object Mapper
Класс Jackson ObjectMapper от FasterXML – это самый простой способ разбора JSON с помощью Java.
Jackson ObjectMapper может анализировать JSON из строки, потока или файла и создавать Java-объект или объектный граф, представляющий разобранный JSON. Этот процесс известен как** десериализация JSON*.
Также мы можем генерировать JSON из Java объектов, что будет **сериализацией Java объектов в JSON*.
Библиотека Jackson предоставляет несколько аннотаций, которые мы можем использовать в наших классах, облегчая нашу работу во время составления карты.
Здесь я расскажу только о тех, которые мы используем ежедневно, но если вы хотите узнать больше, вы можете обратиться к официальной документации jackson-annotations.
- JsonProperty
- JsonInclude
- JsonIgnore
- JsonFormat
- JsonSerialize
- JsonDeserialize
Свойство Json
Является аннотацией маркера для установки логического свойства.
@JsonProperty может быть аннотирован в нестатическом методе setter или getter или нестатическом поле объекта.
Свойство logic используется при сериализации и десериализации JSON.
public class ExemploDTO {
// ... outros campos
@JsonProperty("nome_do_usuario")
private String nomeUsuario;
//... restante da implementação
}
a
С помощью @JsonProperty мы говорим имя ключа источника JSON и устанавливаем его значение в нашу переменную.
* Значение ключа “имя_пользователя” будет привязано к нашей переменной username.
Json Включить
используется для свойств исключения с нулевыми / пустыми или значениями по умолчанию.
Класс без @JsonInclude
public class ExemploDTO {
private int id;
private String nome;
ExemploDTO (int id,String nome) {
this.id = id;
this.name = name;
}
}
{ "id": 15, "nome": null }
Теперь с @JsonInclude
@JsonInclude(JsonInclude.Include.NON_NULL)
public class ExemploDTO {
private int id;
private String nome;
ExemploDTO (int id,String nome) {
this.id = id;
this.nome= nome;
}
}
Выход
{ "id": 15 }
поскольку значение переменной ‘name’ равно null, она была исключена из окончательного json.
Существует 6 типов включения
-
ВСЕГДА
- Значение, указывающее, что свойство должно быть включено всегда, независимо от значения свойства.
-
НЕ_АБСЕНТ
- Значение, указывающее, что свойства включены, если только их значение не является нулевым значением ссылочного типа *(такого как Java 8+ ‘Optional’ или AtomicReference); то есть, что-то, что не будет уважать ненулевое значение.
-
НЕ_ДЕФАУЛЬТ
- Значение этого параметра зависит от контекста: указана ли аннотация для типа POJO (класс) или нет.
Если это тип POJO, то будут исключены только свойства со значениями по умолчанию
Пример:
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
public class Empregado {
private String nome;
private String departamento;
private Integer salario;
private boolean tempoIntegral;
// ...
public class ExemploMain {
public static void main(String[] args) throws IOException {
Empregado empregado = new Empregado ();
empregado .setNome("Sassine");
empregado .setTempoIntegral(false);
empregado .setSalario(Integer.valueOf(0));
ObjectMapper om = new ObjectMapper();
String jsonString = om.writeValueAsString(empregado );
System.out.println(jsonString);
}
}
Выход
{"nome":"Sassine","salario":0 }
На уровне поля или глобальном уровне все свойства, значения которых установлены по умолчанию или пустые значения, пустые списки и т.п. будут исключены…
Выход будет выглядеть примерно так:
{"nome":"Sassine" }
-
NON_EMPTY
- Значение, указывающее, что не следует включать только свойства с нулевым значением, или то, что считается пустым.
-
NON_NULL
- Значение, указывающее, что должны быть включены только свойства с ненулевыми значениями.
-
USE_DEFAULTS
- Псевдо-значение, указывающее, что значения по умолчанию верхнего уровня имеют смысл, чтобы избежать переопределения значения include.
Игнорирование Json
Json ignore работает аналогично Include, но может использоваться только для указания, что поле не будет десериализовано, даже если оно содержит значение.
public class ExemploDTO {
@JsonIgnore
private int id;
private String nome;
ExemploDTO (int id,String nome) {
this.id = id;
this.nome= nome;
}
}
{ "nome": null }
Формат Json
Это аннотация Джексона, используемая для указания способа форматирования полей и/или свойств для вывода в формате JSON.
В частности, эта аннотация позволяет указать, как форматировать значения даты и календаря в соответствии с форматом SimpleDateFormat.
public class ExemploDTO {
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private Date dataVencimento;
@JsonFormat(shape = JsonFormat.Shape.NUMBER)
private ExemploEnum tipoUsuario = ExemploEnum.MODERADOR;
}
Выход:
{ "dataVencimento": "2022-04-26", "tipoUsuario" : 2}
Сериализация Json
Указывает пользовательский сериализатор, который будет использоваться при упаковке сущности
Пример использования пользовательского сериализатора
public class ExemploDTO {
private String name;
@JsonSerialize(using = CustomDateSerializer.class)
private Date dataVencimento;
}
public class CustomDateSerializer extends StdSerializer {
private static SimpleDateFormat FORMATTER = new SimpleDateFormat("dd-MM-yyyy hh:mm:ss");
public CustomDateSerializer() {
this(null);
}
public CustomDateSerializer() {
super(t);
}
@Override
public void serialize(Date value, JsonGenerator gen, SerialzerProvider arg2) throws IOException, JsonProcessingException {
gen.writeString(FORMATTER.format(value));
}
}
Бонус:
В новых версиях java мы используем API java.time, если вам нужно использовать сериализатор для этого, то в jackson lib jsr310 есть следующий импорт:
ToStringSerializer
Десериализация Json
Так же как @JsonSerialize указывает на пользовательский сериализатор, json deserialize указывает на пользовательский десериализатор.
public class JsonDeserializeDTO {
public String nome;
@JsonDeserialize(using = CustomDateDeserializer.class)
public Date dataVencimento;
}
public class CustomDateDeserializer extends StdDeserializer<Date> {
private static SimpleDateFormat formatter = new SimpleDateFormat("dd-MM-yyyy");
public CustomDateDeserializer() {
this(null);
}
public CustomDateDeserializer(Class<?> vc) {
this(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);
}
}
}
Выход:
{ "dataVencimento": "2022-04-26", "nome" : "Sassine"}
Бонус:
В новых версиях java мы используем java.time API, если вам нужно использовать десериализатор для этого, то в jackson’s lib jsr310 есть следующие элементы:
LocalDateTime == LocalDateTimeDeserializer
LocalDate == LocalDateDeserializer
LocalTime == LocalTimeDeserializer
Заключение
Используя эти основные аннотации в своем приложении при манипулировании входными данными в формате JSON, вы оптимизируете много времени и строк кода, которые были бы ответственны за эти преобразования вручную.
И все это в сочетании с javax.validation lib (я скоро сделаю пост о ней) делает сериализацию и манипуляции с JSON в вашем API в чрезвычайно безопасном, чистом объеме с меньшим количеством строк кода для применения этих преобразований и бизнес-правил и легким обслуживанием.