百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

SpringBoot中Jackson控制序列化和反序列化的注解和扩展点总结

lipiwang 2024-11-17 13:26 12 浏览 0 评论

?

Jackson库中,有多个注解和扩展点来支持我们个性化的序列化和反序列化需求。下面做一个总结,建议收藏备用。

  • 一、Jackson中的常用注解
    • 1 @JsonSerialize和@JsonDeserialize
    • 2 @JsonProperty
    • 3 @JsonIgnore
    • 4 @JsonFormat
    • 5 @JsonUnwrapped
    • 6 @JsonAnyGetter
    • 7 @JsonInclude
    • 8 @JsonAlias
    • 9 @JsonIgnoreProperties
    • 10 @JsonManagedReference 和 @JsonBackReference
    • 11 @JsonCreator
    • 12 @JsonTypeInfo
    • 13 @JsonFilter
    • 14 @JsonAnySetter
    • 15 @JsonAppend
    • 16 @JsonIgnoreType
    • 17 @JsonGetter和@JsonSetter
    • 18 @JsonPropertyOrder
  • 二、Jackson 库中的模块
    • 2.1 databind
    • 2.2 annotations
    • 2.3 coreutils
    • 2.4 datatype-jsr310
    • 2.5 jaxrs-json-provider
  • 三、 Jackson库的扩展点
    • 3.1 JsonSerializer和JsonDeserializer
    • 3.2 StdConverter
    • 3.3 JsonNodeFactory
    • 3.4 JsonDeserializerModifier和JsonSerializerModifier
    • 3.5 ValueInstantiator
    • 3.6 ObjectIdResolver
    • 3.7 ObjectIdentityGenerator


一、Jackson中的常用注解

1 @JsonSerialize和@JsonDeserialize

1.1 @JsonSerialize注解

指定自定义的序列化器,控制如何将对象转换为JSON字符串,包括自定义字段值的格式、类型转换等。

1.2 @JsonDeserialize 注解

指定自定义的反序列化器,控制如何将JSON字符串转换为对象,包括处理特殊格式、类型转换等。

import com.fasterxml.jackson.annotation.JsonDeserialize;
import com.fasterxml.jackson.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;

@JsonSerialize(using = CustomSerializer.class)
@JsonDeserialize(using = CustomDeserializer.class)
public class Person {
    private String name;
    private int age;

    // 省略构造函数和getter/setter方法

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person("John", 30);

        String json = mapper.writeValueAsString(person);
        System.out.println(json); 
        // 输出:{"fullName":"John","years":30}

        Person deserializedPerson = mapper.readValue(json, Person.class);
        System.out.println(deserializedPerson);
        // 输出:Person{name='John', age=30}
    }
}

class CustomSerializer extends JsonSerializer<Person> {
    @Override
    public void serialize(Person person, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
        jsonGenerator.writeStartObject();
        jsonGenerator.writeStringField("fullName", person.getName());
        jsonGenerator.writeNumberField("years", person.getAge());
        jsonGenerator.writeEndObject();
    }
}

class CustomDeserializer extends JsonDeserializer<Person> {
    @Override
    public Person deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        JsonNode node = jsonParser.getCodec().readTree(jsonParser);
        String fullName = node.get("fullName").asText();
        int years = node.get("years").asInt();
        return new Person(fullName, years);
    }
}

指定自定义序列化器将Person对象转换为包含"fullName"和 "years" 字段的 JSON 字符串。指定自定义反序列化器将JSON串中的"fullName"和"years"字段解析为Person对象。

2 @JsonProperty

作用:指定在 JSON 序列化和反序列化过程中使用的属性名称。

public class MyClass {
    @JsonProperty("customName")
    private String property;
    // Getter and Setter methods
}

3 @JsonIgnore

作用:指示 Jackson 序列化和反序列化过程中忽略被注解的属性。

public class MyClass {
    @JsonIgnore
    private String property;
    // Getter and Setter methods
}

4 @JsonFormat

序列化或反序列化时,对日期、时间等特殊类型的字段进行格式化的方式。它的作用是控制日期、时间等特殊类型字段的序列化和反序列化格式。

4.1 格式化日期

@JsonFormat 注解来指定日期字段在序列化为 JSON 字符串时的格式,以及在从 JSON 字符串反序列化为 Java 对象时的格式。

import com.fasterxml.jackson.annotation.JsonFormat;

public class Event {
    @JsonFormat(pattern = "yyyy-MM-dd")
    private Date eventDate;

    // 省略构造函数和getter/setter方法
}

4.2 其他格式化选项

@JsonFormat 注解还支持如timezone、shape 等,用于更精细地控制字段的序列化和反序列化行为。

import com.fasterxml.jackson.annotation.JsonFormat;

public class Payment {
    @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ", timezone = "GMT+8")
    private LocalDateTime paymentTime;

    // 省略构造函数和getter/setter方法
}

5 @JsonUnwrapped

使用@JsonUnwrapped 注解时,它会在序列化和反序列化过程中起到以下作用:

5.1 序列化(Serialization)

在序列化过程中,@JsonUnwrapped 注解告诉Jackson库将嵌套对象的属性合并到外层对象中,从而在生成的JSON数据中直接包含嵌套对象的属性。这样可以减少生成的JSON结构中的层级,使其更加扁平化。

5.2 反序列化(Deserialization)

在反序列化过程中,@JsonUnwrapped 注解告诉 Jackson 库将指定的属性值从JSON数据中提取出来,并填充到外层对象的对应属性中。这样可以让 JSON 数据中的扁平结构直接映射到外层对象的属性上,简化了处理嵌套结构的代码逻辑。

使用 :Employe类包含嵌套的Address对象:

import com.fasterxml.jackson.annotation.JsonUnwrapped;

public class Employee {
    private String name;
    
    @JsonUnwrapped
    private Address address;

    // 省略构造函数和getter/setter方法
}

public class Address {
    private String city;
    private String street;
    // 省略构造函数和getter/setter方法
}

一个employee对象:

Employee employee = new Employee("John Doe", new Address("New York", "123 Main St"));

在序列化时,employee 对象将被转换为如下的 JSON 结构:

{
  "name": "John Doe",
  "city": "New York",
  "street": "123 Main St"
}

在反序列化时,以下 JSON 数据:

{
  "name": "Jane Smith",
  "city": "San Francisco",
  "street": "456 Elm St"
}

将会被转换为一个包含相应属性的 Employee 对象。

除了基本用法,@JsonUnwrapped 注解还支持一些属性,如 prefix 和 suffix,用于控制展开的属性在合并到外层对象时是否添加前缀或后缀。

import com.fasterxml.jackson.annotation.JsonUnwrapped;

public class Contact {
    @JsonUnwrapped(prefix = "home_")
    private Address homeAddress;

    @JsonUnwrapped(prefix = "work_")
    private Address workAddress;

    // 省略构造函数和getter/setter方法
}

使用@JsonUnwrapped 注解后,嵌套对象的属性被直接合并到外层对象中,使得JSON数据与Java对象之间的转换更加简洁和直观。

6 @JsonAnyGetter

作用:用于将对象的属性按键值对的形式输出为 Map,包括动态属性。将动态属性以键值对的形式合并到 JSON 中代码

public class MyClass {
    private Map<String, Object> properties = new HashMap<>();

    @JsonAnyGetter
    public Map<String, Object> getProperties() {
        return properties;
    }

    public void addProperty(String key, Object value) {
        properties.put(key, value);
    }
}

@JsonAnyGetter 注解标记了getProperties 方法,将对象的动态属性以键值对的形式输出为 Map。通过addProperty 方法可以动态地添加属性到 properties Map 中。

7 @JsonInclude

用于控制在序列化过程中如何处理属性值为 null 的情况。它的作用是指定在将对象转换为 JSON 字符串时是否包含属性值为 null 的字段。

@JsonInclude 注解可以应用在类级别或属性级别上。

7.1 类级别的 @JsonInclude 注解

当应用在类级别上时,@JsonInclude 注解指示了默认的 null 处理策略,该策略会应用到整个类的所有属性上。

通过设置 @JsonInclude 的 value 属性,可以指定序列化过程中的 null 处理策略,常用的取值包括:

Include.ALWAYS:始终包含属性值为 null 的字段。Include.NON_NULL:仅包含属性值不为 null 的字段。Include.NON_EMPTY:仅包含属性值不为 null 且不为空(如空字符串、空集合)的字段。Include.USE_DEFAULTS:使用默认的 null 处理策略。

7.2 属性级别的@JsonInclude注解

当应用在属性级别上时,@JsonInclude 注解可以覆盖类级别的默认 null 处理策略,为该属性指定独立的 null 处理策略。通过设置 @JsonInclude 的 value 属性,可以指定序列化过程中该属性的 null 处理策略,取值与类级别的注解相同。

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.databind.ObjectMapper;

@JsonInclude(JsonInclude.Include.NON_NULL)
public class Person {
    private String name;
    private Integer age;
    private String address;

    // 省略构造函数和getter/setter方法

    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        Person person = new Person("John", null, null);

        String json = mapper.writeValueAsString(person);
        System.out.println(json); // 输出:{"name":"John"}

        Person deserializedPerson = mapper.readValue(json, Person.class);
        System.out.println(deserializedPerson); // 输出:Person{name='John', age=null, address=null}
    }
}

8 @JsonAlias

作用:指定属性的别名,在反序列化时将别名与属性进行映射。代码

public class MyClass {
    @JsonAlias({"name", "fullName"})
    private String property;
    // Getter and Setter methods
}

9 @JsonIgnoreProperties

作用:指定在序列化和反序列化过程中需要忽略的属性。代码

@JsonIgnoreProperties({"property1", "property2"})
public class MyClass {
    private String property1;
    private String property2;
    private String property3;
    // Getter and Setter methods
}

10 @JsonManagedReference 和 @JsonBackReference

作用:用于解决循环引用的问题,即某个对象与其他对象存在相互引用的情况。**代码****:

public class Parent {
    private String name;
    @JsonManagedReference
    private List<Child> children;
    // Getter and Setter methods
}

public class Child {
    private String name;
    @JsonBackReference
    private Parent parent;
    // Getter and Setter methods
}

@JsonManagedReference 注解用于标注父对象中的子对象集合,而 @JsonBackReference 注解用于标注子对象中的父对象引用。可以防止循环引用导致的无限递归问题。

11 @JsonCreator

作用:在反序列化过程中,用于指定一个静态工厂方法或构造函数,用于创建对象实例。代码

public class MyClass {
    private String property;

    @JsonCreator
    public MyClass(@JsonProperty("property") String property) {
        this.property = property;
    }
    // Getter method for property
}

@JsonCreator注解标注了一个构造函数,@JsonProperty 指定了属性与 JSON 中的字段进行映射。

12 @JsonTypeInfo

作用:在序列化和反序列化过程中,用于处理多态类型。代码

@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonSubTypes({
    @JsonSubTypes.Type(value = Dog.class, name = "dog"),
    @JsonSubTypes.Type(value = Cat.class, name = "cat")
})
public abstract class Animal {
    // Common properties and methods
}

public class Dog extends Animal {
    // Dog-specific properties and methods
}

public class Cat extends Animal {
    // Cat-specific properties and methods
}

@JsonTypeInfo 注解指定了类型信息在序列化和反序列化中的处理方式,@JsonSubTypes 注解标注了派生类与其对应的类型标识。

13 @JsonFilter

用于动态过滤在序列化过程中要包含的属性。在运行时动态地指定要序列化的属性,在某些场景下非常有用,比如根据用户权限或者其他条件决定序列化的内容。

13.1 使用 @JsonFilter 注解定义过滤器

先要定义一个过滤器,将其应用到需要动态过滤的类上。

import com.fasterxml.jackson.annotation.JsonFilter;

@JsonFilter("myFilter")
public class MyDto {
    private String name;
    private int age;
    private String email;
    
    // 省略构造函数和getter/setter方法
}

13.2 配置 ObjectMapper 使用过滤

接下来,配置 ObjectMapper使用这个过滤器。

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ser.impl.SimpleBeanPropertyFilter;
import com.fasterxml.jackson.databind.ser.impl.SimpleFilterProvider;

ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider filterProvider = new SimpleFilterProvider();
filterProvider.addFilter("myFilter", SimpleBeanPropertyFilter.filterOutAllExcept("name", "age"));
mapper.setFilterProvider(filterProvider);

13.3 应用过滤器进行序列化

最后,在进行序列化时,可以指定要使用的过滤器

String json = mapper.writer(filterProvider).writeValueAsString(myDto);

序列化过程中,只会包含 "name" 和 "age" 两个属性,因为在过滤器中指定了这两个属性。

使用 @JsonFilter注解可以实现动态过滤要序列化的属性,根据需求灵活地控制序列化结果,对于构建灵活的API或者处理动态权限控制非常有用。

14 @JsonAnySetter

作用:允许将未匹配到具体字段的键值对动态地注入到 Java 对象中。代码

public class MyClass {
    private Map<String, Object> additionalProperties = new HashMap<>();

    @JsonAnySetter
    public void setAdditionalProperty(String key, Object value) {
        additionalProperties.put(key, value);
    }
}

15 @JsonAppend

作用:允许用户在序列化时动态地添加属性到 JSON 对象中,这些属性可能源自于 Java 对象的不同字段或方法。代码

@Getter
    @Setter
    @AllArgsConstructor(staticName = "of")
    @NoArgsConstructor
    @JsonAppend(attrs = {@JsonAppend.Attr(value = "age"),@JsonAppend.Attr(value = "height")},
                props = {@JsonAppend.Prop(value =TestWriter.class ,type = String.class,name = "version")})
    class JsonPropertyPojo{


        private String sex;

        private String name;

        private String unknown;

    }
    @NoArgsConstructor
    class TestWriter extends VirtualBeanPropertyWriter{


        private TestWriter(BeanPropertyDefinition propDef, Annotations contextAnnotations, JavaType declaredType) {
            super(propDef, contextAnnotations, declaredType);
        }


        @Override
        protected Object value(Object bean, JsonGenerator gen, SerializerProvider prov) throws Exception {

            Field nameField = ReflectionUtils.findField(bean.getClass(),"name");
            ReflectionUtils.makeAccessible(nameField);

           if( nameField.get(bean).toString().length()>2){

               return "1.2";


           }

           return "1.0";

        }

        @Override
        public VirtualBeanPropertyWriter withConfig(MapperConfig<?> config, AnnotatedClass declaringClass, BeanPropertyDefinition propDef, JavaType type) {
            return new TestWriter(propDef, declaringClass.getAnnotations(), type);
        }
    }
    # 测试代码
    @Test
    public void JsonAppendTest() throws Exception{

        CombineJacksonAnnotation.JsonPropertyPojo pojo = CombineJacksonAnnotation.JsonPropertyPojo.of("男","小小刘","some");
        System.out.println(om.writerFor(CombineJacksonAnnotation.JsonPropertyPojo.class).withAttribute("age","10").withAttribute("height","12").writeValueAsString(pojo));

    }
  # 序列化结果如下
{
  "sex" : "男",
  "name" : "小小刘",
  "unknown" : "some",
  "age" : "10",
  "height" : "12",
  "version" : "1.2"
}

@JsonAppend提供两种方式来动态的添加虚拟字段

  • 1 attrs此种方式需要在序列化时候手动的添加Attribute,如 om.writerFor(CombineJacksonAnnotation.JsonPropertyPojo.class).withAttribute("age","10").withAttribute("height","12")
  • 2 props

此种方式比较灵活,但是要实现一个VirtualBeanPropertyWriter类即可,如果真的有这种需求,推荐使用第二种方式来实现

16 @JsonIgnoreType

作用:在序列化和反序列化过程中忽略被注解的类型。这意味着被 @JsonIgnoreType 注解的类型将会被完全忽略,不会被包含在最终生成的 JSON 中,也不会被用于反序列化。@JsonIgnoreType 注解会被用于一些辅助性的、不需要被序列化和反序列化的类型,或者是一些与 JSON 交互无关的类型。

import com.fasterxml.jackson.annotation.JsonIgnoreType;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        MyEntity entity = new MyEntity("John", new AdditionalInfo("some info"));

        String json = mapper.writeValueAsString(entity);
        System.out.println(json); 
        // 输出:{"name":"John"}

        MyEntity deserializedEntity = mapper.readValue(json, MyEntity.class);
        System.out.println(deserializedEntity); 
        // 输出:MyEntity{name='John', additionalInfo=null}
    }
}

@JsonIgnoreType
class AdditionalInfo {
    private String info;
    // 省略构造函数和getter/setter方法
}

class MyEntity {
    private String name;
    private AdditionalInfo additionalInfo;
    // 省略构造函数和getter/setter方法
}

17 @JsonGetter和@JsonSetter

作用:用于指定在序列化和反序列化过程中 JSON 属性的命名规则以及自定义属性的读取和写入方法。:

17.1 @JsonGetter 注解

  • 1) 用于指定一个非标准的getter方法作为JSON属性的读取方法。
  • 2) 通过在非标准的getter方法上使用@JsonGetter 注解,可以指定该方法对应的JSON属性的名称。
  • 3) 可将Java对象中的属性映射到不同于属性名的JSON属性

17.2 @JsonSetter 注解

  • 1)用于指定一个非标准的 setter 方法作为 JSON 属性的写入方法。
  • 2)通过在非标准的 setter 方法上使用 @JsonSetter 注解,可以指定该方法对应的 JSON 属性的名称。
  • 3) 可将JSON中的属性值映射到不同于属性名的 Java 对象属性,更灵活的属性赋值。
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonSetter;
import com.fasterxml.jackson.databind.ObjectMapper;

public class Main {
    public static void main(String[] args) throws Exception {
        ObjectMapper mapper = new ObjectMapper();
        String json = "{\"first_name\":\"John\",\"last_name\":\"Doe\"}";
        Person person = mapper.readValue(json, Person.class);
        System.out.println(person.getFullName()); // 输出:John Doe

        String outputJson = mapper.writeValueAsString(person);
        System.out.println(outputJson); // 输出:{"first_name":"John","last_name":"Doe"}
    }
}

class Person {
    private String firstName;
    private String lastName;

    @JsonGetter("full_name")
    public String getFullName() {
        return firstName + " " + lastName;
    }

    @JsonSetter("first_name")
    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    @JsonSetter("last_name")
    public void setLastName(String lastName) {
        this.lastName = lastName;
    }
}

getFullName方法使用@JsonGetter("full_name")注解,指定返回的全名属性对应的JSON 属性名称为"full_name"。setFirstName和setLastName方法使用了@JsonSetter注解,指定它们对应的JSON属性名称。

18 @JsonPropertyOrder

作用:将pojo对象序列化成为json字符串时,使用@JsonPropertyOrder可以指定属性在json字符串中的顺序

二、Jackson 库中的模块

Jackson库中比较常用的模块:

2.1 databind

作用:提供了 JSON 序列化和反序列化的核心功能,可以将 Java 对象和 JSON 数据相互转换。

代码

ObjectMapper objectMapper = new ObjectMapper();
MyClass myObject = objectMapper.readValue(json, MyClass.class);
String json = objectMapper.writeValueAsString(myObject);

2.2 annotations

作用:提供了一系列注解,用于控制序列化和反序列化过程中的行为和选项。代码

public class MyClass {
    @JsonProperty("my_property")
    private String property;
    // Getter and Setter methods
}

2.3 coreutils

作用:提供一些基础工具类和函数,用于支持序列化和反序列化过程中所需的类型转换和其他操作。代码

// Convert JSON string to JsonNode object
JsonNode jsonNode = objectMapper.readTree(jsonString);

// Convert object to Map
Map<String, Object> map = objectMapper.convertValue(myObject, new TypeReference<Map<String, Object>>() {});

// Convert object to byte array
byte[] bytes = objectMapper.writeValueAsBytes(myObject);

2.4 datatype-jsr310

作用:提供对 Java 8 时间类的支持,包括 LocalDateTime、ZonedDateTime、Instant 等代码

ObjectMapper objectMapper = new ObjectMapper()
    .registerModule(new JavaTimeModule())
    .configure(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);

用JavaTimeModule注册模块,启用对Java8时间类的支持。

2.5 jaxrs-json-provider

作用:提供了 JAX-RS 规范中 JSON 消息转换器的实现,适用于 Web 应用程序中返回 JSON 数据的场景。代码

@GET
@Produces(MediaType.APPLICATION_JSON)
public Response getMyObject() {
    MyClass myObject = myService.getMyObject();
    return Response.ok(myObject).build();
}

// Register JSON provider
register(JacksonJaxbJsonProvider.class);

三、 Jackson库的扩展点

Jackson库提供了一些扩展点,使得用户可以扩展序列化和反序列化过程中的行为和选项。一些常用的扩展点:

3.1 JsonSerializer和JsonDeserializer

作用:用于自定义 Java 对象和 JSON 数据的转换过程。代码

public class MyClassSerializer extends JsonSerializer<MyClass> {
    @Override
    public void serialize(MyClass value, JsonGenerator gen, SerializerProvider serializers) throws IOException {
        gen.writeStartObject();
        gen.writeStringField("my_property", value.getProperty());
        gen.writeEndObject();
    }
}

public class MyClassDeserializer extends JsonDeserializer<MyClass> {
    @Override
    public MyClass deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
        JsonNode jsonNode = p.getCodec().readTree(p);
        return new MyClass(jsonNode.get("my_property").asText());
    }
}

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addSerializer(MyClass.class, new MyClassSerializer());
module.addDeserializer(MyClass.class, new MyClassDeserializer());
objectMapper.registerModule(module);

3.2 StdConverter

作用:用于提供类型转换的实现,可以用于自定义注解的处理等场景。代码

@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Masked {
    boolean value() default true;
}

public class MaskedStringConverter extends StdConverter<String, String> {
    @Override
    public String convert(String value) {
        if (value == null) {
            return null;
        }
        if (value.length() > 4) {
            StringBuilder builder = new StringBuilder();
            for (int i = 0; i < value.length(); i++) {
                if (i < value.length() - 4) {
                    builder.append('*');
                } else {
                    builder.append(value.charAt(i));
                }
            }
            return builder.toString();
        } else {
            return value;
        }
    }
}

public class MaskedStringModifier extends BeanPropertyModifierBase {
    @Override
    public BeanPropertyDefinition updateBuilder(SerializationConfig config,
                                                BeanDescription beanDesc,
                                                BeanPropertyDefinition propDef) {
        AnnotatedField field = propDef.getField();
        if (field == null) {
            return propDef;
        }
        Masked masked = field.getAnnotation(Masked.class);
        if (masked == null || !masked.value()) {
            return propDef;
        }
        return propDef.withSerializer(new StdDelegatingSerializer(new MaskedStringConverter()));
    }
}

ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.setSerializerModifier(new MaskedStringModifier());
objectMapper.registerModule(module);

3.3 JsonNodeFactory

作用:用于提供自定义的 JsonNode 对象的生成策略。代码

JsonNodeFactory customNodeFactory = new JsonNodeFactory() {
    @Override
    public ObjectNode objectNode() {
        return new CustomObjectNode(this);
    }
};

class CustomObjectNode extends ObjectNode {
    public CustomObjectNode(JsonNodeFactory nc) {
        super(nc);
    }

    public CustomObjectNode(JsonNodeFactory nc, Map<String, JsonNode> m) {
        super(nc, m);
    }

    @Override
    public String toString() {
        return "CustomObjectNode[" + super.toString() + "]";
    }
}

ObjectMapper objectMapper = new ObjectMapper();
objectMapper.setNodeFactory(customNodeFactory);

3.4 JsonDeserializerModifier和JsonSerializerModifier

作用:允许对默认的 JsonDeserializer 和 JsonSerializer 进行修改或替换。代码

public class MyJsonSerializerModifier extends BeanSerializerModifier {
    @Override
    public JsonSerializer<?> modifySerializer(SerializationConfig config,
                                               BeanDescription beanDesc,
                                               JsonSerializer<?> serializer) {
        if (beanDesc.getBeanClass() == MyClass.class) {
            return new MyJsonSerializer();
        }
        return super.modifySerializer(config, beanDesc, serializer);
    }
}

SimpleModule module = new SimpleModule();
module.setSerializerModifier(new MyJsonSerializerModifier());
objectMapper.registerModule(module);

3.5 ValueInstantiator

作用:用于自定义对象实例化的逻辑,例如使用工厂方法或者构造器参数注入等。代码

public class MyClassValueInstantiator extends ValueInstantiator.Base {
    @Override
    public Object createUsingDefault(DeserializationContext ctxt) throws IOException {
        // 可以在此处添加自定义的实例化逻辑
        return new MyClass();
    }
}

SimpleModule module = new SimpleModule();
module.addValueInstantiator(MyClass.class, new MyClassValueInstantiator());
objectMapper.registerModule(module);

3.6 ObjectIdResolver

作用:用于自定义对象与唯一标识符之间的映射关系,用于处理循环引用等场景。代码

public class MyObjectIdResolver implements ObjectIdResolver {
    // 实现方法...
}

DefaultSerializerProvider.Impl sp = new DefaultSerializerProvider.Impl();
sp.setObjectIdResolver(new MyObjectIdResolver());
objectMapper.setSerializerProvider(sp);

3.7 ObjectIdentityGenerator

作用:用于生成对象唯一标识符(Object Id)。代码

public class MyObjectIdentityGenerator extends ObjectIdentityGenerator<MyObject> {
    // 实现方法...
}

SimpleModule module = new SimpleModule();
module.setIdentityInfoGenerator(new MyObjectIdentityGenerator());
objectMapper.registerModule(module);

相关推荐

前端入门——css 网格轨道详细介绍

上篇前端入门——cssGrid网格基础知识整体大概介绍了cssgrid的基本概念及使用方法,本文将介绍创建网格容器时会发生什么?以及在网格容器上使用行、列属性如何定位元素。在本文中,将介绍:...

Islands Architecture(孤岛架构)在携程新版首页的实践

一、项目背景2022,携程PC版首页终于迎来了首次改版,完成了用户体验与技术栈的全面升级。作为与用户连接的重要入口,旧版PC首页已经陪伴携程走过了22年,承担着重要使命的同时,也遇到了很多问题:维护/...

HTML中script标签中的那些属性

HTML中的<script>标签详解在HTML中,<script>标签用于包含或引用JavaScript代码,是前端开发中不可或缺的一部分。通过合理使用<scrip...

CSS 中各种居中你真的玩明白了么

页面布局中最常见的需求就是元素或者文字居中了,但是根据场景的不同,居中也有简单到复杂各种不同的实现方式,本篇就带大家一起了解下,各种场景下,该如何使用CSS实现居中前言页面布局中最常见的需求就是元...

CSS样式更改——列表、表格和轮廓

上篇文章主要介绍了CSS样式更改篇中的字体设置Font&边框Border设置,这篇文章分享列表、表格和轮廓,一起来看看吧。1.列表List1).列表的类型<ulstyle='list-...

一文吃透 CSS Flex 布局

原文链接:一文吃透CSSFlex布局教学游戏这里有两个小游戏,可用来练习flex布局。塔防游戏送小青蛙回家Flexbox概述Flexbox布局也叫Flex布局,弹性盒子布局。它决定了...

css实现多行文本的展开收起

背景在我们写需求时可能会遇到类似于这样的多行文本展开与收起的场景:那么,如何通过纯css实现这样的效果呢?实现的难点(1)位于多行文本右下角的展开收起按钮。(2)展开和收起两种状态的切换。(3)文本...

css 垂直居中的几种实现方式

前言设计是带有主观色彩的,同样网页设计中的css一样让人摸不头脑。网上列举的实现方式一大把,或许在这里你都看到过,但既然来到这里我希望这篇能让你看有所收获,毕竟这也是前端面试的基础。实现方式备注:...

WordPress固定链接设置

WordPress设置里的最后一项就是固定链接设置,固定链接设置是决定WordPress文章及静态页面URL的重要步骤,从站点的SEO角度来讲也是。固定链接设置决定网站URL,当页面数少的时候,可以一...

面试发愁!吃透 20 道 CSS 核心题,大厂 Offer 轻松拿

前端小伙伴们,是不是一想到面试里的CSS布局题就发愁?写代码时布局总是对不齐,面试官追问兼容性就卡壳,想跳槽却总被“多列等高”“响应式布局”这些问题难住——别担心!从今天起,咱们每天拆解一...

3种CSS清除浮动的方法

今天这篇文章给大家介绍3种CSS清除浮动的方法。有一定的参考价值,有需要的朋友可以参考一下,希望对大家有所帮助。首先,这里就不讲为什么我们要清楚浮动,反正不清除浮动事多多。下面我就讲3种常用清除浮动的...

2025 年 CSS 终于要支持强大的自定义函数了?

大家好,很高兴又见面了,我是"高级前端进阶",由我带着大家一起关注前端前沿、深入前端底层技术,大家一起进步,也欢迎大家关注、点赞、收藏、转发!1.什么是CSS自定义属性CSS自...

css3属性(transform)的一个css3动画小应用

闲言碎语不多讲,咱们说说css3的transform属性:先上效果:效果说明:当鼠标移到a标签的时候,从右上角滑出二维码。实现方法:HTML代码如下:需要说明的一点是,a链接的跳转需要用javasc...

CSS基础知识(七)CSS背景

一、CSS背景属性1.背景颜色(background-color)属性值:transparent(透明的)或color(颜色)2.背景图片(background-image)属性值:none(没有)...

CSS 水平居中方式二

<divid="parent"><!--定义子级元素--><divid="child">居中布局</div>...

取消回复欢迎 发表评论: