• Jackson 中的 @JsonProperty 和 @JsonAlias 的区别


    1. 背景

    Spring项目中,使用到Jackson用来做Json对象的序列化和反序列化。这里就涉及到了自定义字段名称,通常可以使用 @JsonProperty@JsonAlias ,那这两者的区别是什么呢?

    简单的说,@JsonProperty 支持序列化和反序列化,而 @JsonAlias 仅支持反序列化

    2. 验证

    pom依赖:

    <dependency>
        <groupId>com.fasterxml.jackson.coregroupId>
        <artifactId>jackson-databindartifactId>
        <version>2.14.3version>
    dependency>
    
    • 1
    • 2
    • 3
    • 4
    • 5

    Java 验证程序:

    package com.ysx.utils.json.jackson;
    
    import com.fasterxml.jackson.annotation.JsonAlias;
    import com.fasterxml.jackson.annotation.JsonProperty;
    import com.fasterxml.jackson.core.JsonProcessingException;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import org.junit.jupiter.api.Assertions;
    import org.junit.jupiter.api.DisplayName;
    import org.junit.jupiter.api.Test;
    
    import static org.junit.jupiter.api.Assertions.assertEquals;
    import static org.junit.jupiter.api.Assertions.assertFalse;
    import static org.junit.jupiter.api.Assertions.assertTrue;
    
    /**
     * @author youngbear
     * @email youngbear@aliyun.com
     * @date 2023-09-22 21:24
     * @blog ...
     * @github ...
     * @description @JasonProperty和@JsonAlias的用法和区别
     */
    public class JsonPropertyJsonAliasTest {
    
        @Test
        @DisplayName("序列化测试-@JsonProperty支持序列化-@JsonAlias不支持序列化")
        public void serializationTest() throws JsonProcessingException {
            ObjectMapper objectMapper = new ObjectMapper();
            TestModel model = new TestModel();
            model.setA1("a1Value");
            model.setB1("b1Value");
            String jsonString = objectMapper.writeValueAsString(model);
            // {"b1":"b1Value","a_1":"a1Value"}
            assertTrue(jsonString.contains("a_1"));
            assertFalse(jsonString.contains("b_1"));
        }
    
        @Test
        @DisplayName("反序列化测试-支持自定义字段名称-@JsonProperty支持反序列化-@JsonAlias支持反序列化")
        public void deserializationTest1() throws JsonProcessingException {
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = "{\"b1\":\"b1Value\",\"a_1\":\"a1Value\"}";
            TestModel testModel = objectMapper.readValue(jsonString, TestModel.class);
            assertEquals("a1Value", testModel.getA1());
            assertEquals("b1Value", testModel.getB1());
        }
    
        @Test
        @DisplayName("反序列化测试-@JsonProperty仅支持自定义名称")
        public void deserializationTest2() throws JsonProcessingException {
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = "{\"a_1\":\"a1Value\"}";
            TestModel testModel = objectMapper.readValue(jsonString, TestModel.class);
            assertEquals("a1Value", testModel.getA1());
    
            String jsonString2 = "{\"a1\":\"a1Value\"}";
            Assertions.assertThrows(JsonProcessingException.class,
                    () -> objectMapper.readValue(jsonString2, TestModel.class));
        }
    
        @Test
        @DisplayName("反序列化测试-@JsonAlias支持原有字段名称和自定义字段名称反序列化")
        public void deserializationTest3() throws JsonProcessingException {
            ObjectMapper objectMapper = new ObjectMapper();
            String jsonString = "{\"b_1\":\"b1Value\"}";
            TestModel testModel = objectMapper.readValue(jsonString, TestModel.class);
            assertEquals("b1Value", testModel.getB1());
    
            String jsonString2 = "{\"b1\":\"b1Value\"}";
            TestModel testModel2 = objectMapper.readValue(jsonString2, TestModel.class);
            assertEquals("b1Value", testModel2.getB1());
        }
    
        public static class TestModel {
            @JsonProperty("a_1")
            private String a1;
    
            @JsonAlias("b_1")
            private String b1;
    
            public String getA1() {
                return a1;
            }
    
            public void setA1(String a1) {
                this.a1 = a1;
            }
    
            public String getB1() {
                return b1;
            }
    
            public void setB1(String b1) {
                this.b1 = b1;
            }
        }
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    • 57
    • 58
    • 59
    • 60
    • 61
    • 62
    • 63
    • 64
    • 65
    • 66
    • 67
    • 68
    • 69
    • 70
    • 71
    • 72
    • 73
    • 74
    • 75
    • 76
    • 77
    • 78
    • 79
    • 80
    • 81
    • 82
    • 83
    • 84
    • 85
    • 86
    • 87
    • 88
    • 89
    • 90
    • 91
    • 92
    • 93
    • 94
    • 95
    • 96
    • 97
    • 98

    3. 总结

    从验证程序可以得出以下结论:

    • @JsonProperty 和 @JsonAlias 均支持反序列化(deserialization)时自定义字段名称。
    • @JsonProperty 支持序列化(serialization)时自定义字段名称,而 @JsonAlias 不支持序列化时自定义字段。
    • @JsonProperty 在反序列化时,仅支持自定义后的字段名称,不支持原有的字段名称;而 @JsonAlias 同时支持自定义和原有的字段名称。

    这些可以从官方的API注释中获取到:

    com.fasterxml.jackson.annotation.JsonProperty

    /**
     * Marker annotation that can be used to define a non-static
     * method as a "setter" or "getter" for a logical property
     * (depending on its signature),
     * or non-static object field to be used (serialized, deserialized) as
     * a logical property.
     * 省略其他注释
     */
    @Target({ElementType.ANNOTATION_TYPE, ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER})
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotation
    public @interface JsonProperty
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    解释:

    @JsonProperty 可以用在一个非静态的方法或者属性上,用来设置逻辑的属性名(支持序列化和反序列化)。

    com.fasterxml.jackson.annotation.JsonAlias

    /**
     * Annotation that can be used to define one or more alternative names for
     * a property, accepted during deserialization as alternative to the official
     * name. Alias information is also exposed during POJO introspection, but has
     * no effect during serialization where primary name is always used.
     * 省略其他注释
     */
    @Target({ElementType.ANNOTATION_TYPE, // for combo-annotations
        ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER// for properties (field, setter, ctor param)
    })
    @Retention(RetentionPolicy.RUNTIME)
    @JacksonAnnotation
    public @interface JsonAlias
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13

    解释:

    @JsonAlias 在反序列化时,支持了一个或者多个可选的名称,且不会对其本身的名称有影响。

    4. 参考

  • 相关阅读:
    jdk17新特性
    1.网络IO与select学习
    JVM 参数
    状态压缩dp蒙德里安的梦想
    Java+Tif图片转Jpg
    Linux的iproute2 : ip address ip route ip link 笔记221103
    Java中对象转型
    没用的知识增加了,尝试用文心实现褒义词贬义词快速分类
    机器视觉Halcon中read_image算子探究与学习
    Rust3 Using Structs to Structure Related Data & Enums and Pattern Matching
  • 原文地址:https://blog.csdn.net/Next_Second/article/details/133190879