Во время Национального дня я написал учебник:Easy Learning Jackson Руководство по разработке в кармане программиста, Это один из них.
Джексон поддерживает сериализацию и десериализацию, используя имя JSON, отличное от имени поля объекта (используется внутри Jackson) при обработке данных вместо исходного имени поля.
В основном существует несколько методов реализации:
- Используйте @JsonProperty, чтобы указать фиксированное имя для сопоставления имен;
- Используйте предопределенную стратегию именования PropertyNamingStrategy, чтобы установить глобальную или индивидуальную стратегию именования классов;
- Расширьте возможности PropertyNamingStrategy для реализации пользовательской стратегии именования, поддержки чтения и записи с использованием различных стратегий именования.
Эта статья основана на версии Jackson 2.11.2, начните изучение прямо сейчас.
имя свойства @JsonProperty
Для полей, имена которых необходимо изменить, вы можете добавить аннотацию @JsonProperty к полю или методу получения, чтобы указать фиксированное имя для замены исходного имени поля.
public class AnimalPropertyName {
@JsonProperty("animalName") // 字段重命名. 可以对字段或getter进行声明
private String name;
private int sex;
private Integer weight;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@JsonProperty("animalSex") // 字段重命名. 可以对字段或getter进行声明
public int getSex() {
return sex;
}
public void setSex(int sex) {
this.sex = sex;
}
public Integer getWeight() {
return weight;
}
public void setWeight(Integer weight) {
this.weight = weight;
}
@Override
public String toString() {
return "Animal [name=" + name + ", sex=" + sex + ", weight=" + weight + "]";
}
}
/**
* 使用@JsonProperty("字段别名")注解,序列化和反序列化时使用指定的名称替代字段名
*
* @throws IOException
*/
@Test
public void propertyName() throws IOException {
AnimalPropertyName animal = new AnimalPropertyName();
animal.setName("sam");
animal.setSex(26);
animal.setWeight(100);
ObjectMapper mapper = new ObjectMapper();
// 序列化
String jsonString = mapper.writeValueAsString(animal);
System.out.println(jsonString);
// 正确反序列化
String jsonString2 = "{\"weight\":200,\"animalName\":\"sam2\",\"animalSex\":2}";
AnimalPropertyName animal2 = mapper.readValue(jsonString2, AnimalPropertyName.class);
System.out.println(animal2.toString());
// 错误反序列化. 不能使用原来的字段名name和sex,需要使用注解的名称animalName和animalSex
String jsonString3 = "{\"weight\":200,\"name\":\"sam2\",\"sex\":2}";;
AnimalPropertyName animal3 = mapper.readValue(jsonString3, AnimalPropertyName.class);
System.out.println(animal3.toString());
}
Результаты:
{"weight":100,"animalName":"sam","animalSex":26}
Animal [name=sam2, sex=2, weight=200]
com.fasterxml.jackson.databind.exc.UnrecognizedPropertyException: Unrecognized field "name" ...
Видно, что сериализация первой строки и десериализация второй строки соответствуют нашим ожиданиям.
Но вторая десериализация выдает исключение, что поле имени не распознано.
Разница между первой и второй десериализацией заключается в том, что в первый раз используется имя свойства после сопоставления, а во второй раз используется имя поля объекта.
То есть, если указано имя свойства, указанное имя свойства необходимо использовать при сериализации и десериализации.
Стратегия именования
Используя имя атрибута, вы можете задать разные имена для разных полей, и это имя является фиксированным.
Если все обрабатываемые поля должны соответствовать одним и тем же правилам именования, вы можете использовать стратегию именования PropertyNamingStrategy, чтобы упростить операцию именования.
глобальная стратегия именования
Джексон предоставляет нам 6 стратегий именования по умолчанию.
public class AnimalNaming {
private String animalName;
private int animalSex;
private int animalWeight;
public String getAnimalName() {
return animalName;
}
public void setAnimalName(String animalName) {
this.animalName = animalName;
}
public int getAnimalSex() {
return animalSex;
}
public void setAnimalSex(int animalSex) {
this.animalSex = animalSex;
}
public int getAnimalWeight() {
return animalWeight;
}
public void setAnimalWeight(int animalWeight) {
this.animalWeight = animalWeight;
}
@Override
public String toString() {
return "AnimalNaming [animalName=" + animalName + ", animalSex=" + animalSex + ", animalWeight=" + animalWeight
+ "]";
}
}
/**
* 使用预定义的属性命名策略
*
* @throws IOException
*/
@Test
public void naming() throws IOException {
AnimalNaming animal = new AnimalNaming();
animal.setAnimalName("sam");
animal.setAnimalSex(1);
animal.setAnimalWeight(100);
// 驼峰命名,字段的首字母小写. {"animalName":"sam","animalSex":1,"animalWeight":100}
ObjectMapper mapper1 = new ObjectMapper();
mapper1.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CAMEL_CASE);
System.out.println(mapper1.writeValueAsString(animal));
// 驼峰命名,字段的首字母大写. {"AnimalName":"sam","AnimalSex":1,"AnimalWeight":100}
ObjectMapper mapper2 = new ObjectMapper();
mapper2.setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE);
System.out.println(mapper2.writeValueAsString(animal));
// 字段小写,多个单词以下划线_分隔. {"animal_name":"sam","animal_sex":1,"animal_weight":100}
ObjectMapper mapper3 = new ObjectMapper();
mapper3.setPropertyNamingStrategy(PropertyNamingStrategy.SNAKE_CASE);
System.out.println(mapper3.writeValueAsString(animal));
// 字段小写,多个单词以中横线-分隔. {"animal-name":"sam","animal-sex":1,"animal-weight":100}
ObjectMapper mapper4 = new ObjectMapper();
mapper4.setPropertyNamingStrategy(PropertyNamingStrategy.KEBAB_CASE);
System.out.println(mapper4.writeValueAsString(animal));
// 字段小写,多个单词间无分隔符. {"animalname":"sam","animalsex":1,"animalweight":100}
ObjectMapper mapper5 = new ObjectMapper();
mapper5.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE);
System.out.println(mapper5.writeValueAsString(animal));
// 字段小写,多个单词以点号.分隔. {"animal.name":"sam","animal.sex":1,"animal.weight":100}
ObjectMapper mapper6 = new ObjectMapper();
mapper6.setPropertyNamingStrategy(PropertyNamingStrategy.LOWER_DOT_CASE);
System.out.println(mapper6.writeValueAsString(animal));
}
Результаты:
{"animalName":"sam","animalSex":1,"animalWeight":100}
{"AnimalName":"sam","AnimalSex":1,"AnimalWeight":100}
{"animal_name":"sam","animal_sex":1,"animal_weight":100}
{"animal-name":"sam","animal-sex":1,"animal-weight":100}
{"animalname":"sam","animalsex":1,"animalweight":100}
{"animal.name":"sam","animal.sex":1,"animal.weight":100}
Укажите стратегию именования через ObjectMapper, который является глобальным. То есть, пока используется ObjectMapper, будет применяться стратегия именования.
Стратегия именования для одного класса
Если стратегия именования должна воздействовать только на определенный класс, вы можете использовать аннотацию @JsonNaming.
@JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)
public class AnimalJSONNaming {
private String animalName;
private int animalSex;
private int animalWeight;
public String getAnimalName() {
return animalName;
}
public void setAnimalName(String animalName) {
this.animalName = animalName;
}
public int getAnimalSex() {
return animalSex;
}
public void setAnimalSex(int animalSex) {
this.animalSex = animalSex;
}
public int getAnimalWeight() {
return animalWeight;
}
public void setAnimalWeight(int animalWeight) {
this.animalWeight = animalWeight;
}
@Override
public String toString() {
return "AnimalNaming [animalName=" + animalName + ", animalSex=" + animalSex + ", animalWeight=" + animalWeight
+ "]";
}
}
/**
* 使用@JsonNaming注解,指定属性命名策略
*
* @throws IOException
*/
@Test
public void jsonNaming() throws IOException {
AnimalJSONNaming animal = new AnimalJSONNaming();
animal.setAnimalName("sam");
animal.setAnimalSex(1);
animal.setAnimalWeight(100);
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.writeValueAsString(animal));
}
Результаты:
{"animal_name":"sam","animal_sex":1,"animal_weight":100}
индивидуальная стратегия именования
Интерфейс стратегии именования — это PropertyNamingStrategy, и все указанные выше предопределенные стратегии наследуются от PropertyNamingStrategyBase.
PropertyNamingStrategyBase определяется следующим образом:
public static abstract class PropertyNamingStrategyBase extends PropertyNamingStrategy
{
@Override
public String nameForField(MapperConfig<?> config, AnnotatedField field, String defaultName)
{
return translate(defaultName);
}
@Override
public String nameForGetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
return translate(defaultName);
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName)
{
return translate(defaultName);
}
@Override
public String nameForConstructorParameter(MapperConfig<?> config, AnnotatedParameter ctorParam,
String defaultName)
{
return translate(defaultName);
}
public abstract String translate(String propertyName);
}
Видно, что если вы хотите реализовать собственную стратегию именования, вам нужно просто унаследовать PropertyNamingStrategyBase и реализовать метод translate().
/**
* 自定义命名策略,为字段添加下划线前缀
*/
@SuppressWarnings("serial")
public static class AppendPrefixStrategy extends PropertyNamingStrategyBase {
@Override
public String translate(String input){
return '_' + input;
}
}
/**
* 自定义命名策略
*
* @throws IOException
*/
@Test
public void customNaming() throws IOException {
AnimalNaming animal = new AnimalNaming();
animal.setAnimalName("sam");
animal.setAnimalSex(1);
animal.setAnimalWeight(100);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new AppendPrefixStrategy());
System.out.println(mapper.writeValueAsString(animal));
String jsonString = "{\"_animalName\":\"sam\",\"_animalSex\":1,\"_animalWeight\":100}";
// String jsonString = "{\"animalName\":\"sam\",\"animalSex\":1,\"animalWeight\":100}";
AnimalNaming animal2 = mapper.readValue(jsonString, AnimalNaming.class);
System.out.println(animal2.toString());
}
Результаты:
{"_animalName":"sam","_animalSex":1,"_animalWeight":100}
AnimalNaming [animalName=sam, animalSex=1, animalWeight=100]
Для более сложных стратегий именования каждый метод в PropertyNamingStrategy может быть реализован отдельно.
Например, при десериализации вы хотите использовать исходное имя поля вместо имени с префиксом.
/**
* 自定义命名策略,为字段添加下划线前缀,其中setter方法使用默认的字段名
*/
@SuppressWarnings("serial")
public static class AppendPrefixStrategyForSetter extends PropertyNamingStrategyBase {
@Override
public String translate(String input){
return '_' + input;
}
@Override
public String nameForSetterMethod(MapperConfig<?> config, AnnotatedMethod method, String defaultName) {
return defaultName;
}
}
/**
* 自定义命名策略
*
* @throws IOException
*/
@Test
public void customNamingForSetter() throws IOException {
AnimalNaming animal = new AnimalNaming();
animal.setAnimalName("sam");
animal.setAnimalSex(1);
animal.setAnimalWeight(100);
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(new AppendPrefixStrategyForSetter());
System.out.println(mapper.writeValueAsString(animal));
// String jsonString = "{\"_animalName\":\"sam\",\"_animalSex\":1,\"_animalWeight\":100}";
String jsonString = "{\"animalName\":\"sam\",\"animalSex\":1,\"animalWeight\":100}";
AnimalNaming animal2 = mapper.readValue(jsonString, AnimalNaming.class);
System.out.println(animal2.toString());
}
Результаты:
{"_animalName":"sam","_animalSex":1,"_animalWeight":100}
AnimalNaming [animalName=sam, animalSex=1, animalWeight=100]
резюме
Джексон предоставляет множество методов для поддержки гибкого именования полей.
Самый простой и понятный способ — использовать аннотацию @JsonProperty для присвоения имени полю.
Если правила именования одинаковы, вы можете использовать стратегию именования PropertyNamingStrategy для упрощения написания кода.
Стратегия именования может быть глобальным или только для определенного класса.
Если правила именования более сложны, вы можете реализовать правила именования самостоятельно, чтобы удовлетворить фактические потребности.
Вы можете просто наследовать от PropertyNamingStrategyBase или от PropertyNamingStrategy для реализации более гибкой стратегии именования.
Ссылаться на
Woohoo. Возьмите арлингтон-терьера.com/Jackson-So…
---Просьба указывать автора и источник при перепечатке статей на этом сайте Binarylife.icu, просьба не использовать в каких-либо коммерческих целях---
обо мне
Публичный аккаунт: Binary Road
Руководство:996geek.com
Блог:binarylife.icu