Immutable Lombok annotated class with Jackson

后端 未结 9 2135
再見小時候
再見小時候 2020-12-25 13:02

What is the preferred way to create class that is

  • Immutable
  • Can be serialized/deserialized with Jackson
  • Human-readable and with low level of
相关标签:
9条回答
  • 2020-12-25 13:41

    Another alternative that is much less verbose:

    @Data
    @Setter(AccessLevel.NONE)
    public class Clazz {
        private String field;
    } 
    

    Of course, you could still have some private method that modifies the field directly, but it would be very unlikely to even have any actual code in a @Data POJO, so this would hopefully not happen.

    Disclaimer: This will have the side-effect (perhaps beneficial) of not letting regular Java code create the object since there is only a default constructor with no mutators. To allow for normal construction you will need 2 more annotations:

    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    @Setter(AccessLevel.NONE)
    public class Clazz {
        private String field;
    } 
    
    0 讨论(0)
  • 2020-12-25 13:45

    Answer by Thomas Fritsch worked perfectly with Spring Boot after adding Jackson Dataformat dependency in pom.

    @Data
    @Builder(builderClassName = "PointBuilder")
    @JsonDeserialize(builder = Point.PointBuilder.class)
    public class Point {
    
        private final int x;
    
        private final int y;
    
        @JsonPOJOBuilder(withPrefix = "")
        public static class PointBuilder {
            // Lombok will add constructor, setters, build method
        }
    }
    
    <!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-xml -->
    <dependency>
        <groupId>com.fasterxml.jackson.dataformat</groupId>
        <artifactId>jackson-dataformat-xml</artifactId>
    </dependency>
    
    0 讨论(0)
  • 2020-12-25 13:47

    add ConstructorProperties:

    • Create a lombok.config file in an appropriate location with the line: lombok.anyConstructor.addConstructorProperties = true
    • Add lombok @Value annotation to your class to make it immutable

    Then serialization and deserialization by Jackson works as expected.

    This method:

    • meets the criteria
    • has less boilerplace than the previous top answer
    • works on v1.16.20 (January 9th, 2018) and later

    Edit: 2020-08-16

    • Note: Using @Builder with @Value causes this solution to fail. (Thanks to comment from @guilherme-blanco below.) However, if you also add e.g. @AllArgsConstructor it does still work as expected.
    0 讨论(0)
  • 2020-12-25 13:47

    I've just solved it using this way:

    @Value
    @Builder(setterPrefix = "with")
    @JsonDeserialize(builder = Clazz.ClazzBuilder.class)
    public class Clazz {
        private String field;
    }
    

    In that case, you have to use the builder methods like withField(...), which is the default behaviour used by jackson.

    0 讨论(0)
  • 2020-12-25 13:50

    As of 15 October 2020 Lombok (v1.18.16), you should simply be able to use the @Jacksonized annotation.

    @Jacksonized @Builder
    @JsonIgnoreProperties(ignoreUnknown = true)
    public class JacksonExample {
      private List<Foo> foos;
    }
    

    As described in the linked documentation, this annotation:

    • configures Jackson to use the builder for deserialisation,
    • copies field-specific configuration down from the annotated class to the generated builder (e.g. @JsonIgnoreProperties), and
    • aligns the Jackson prefix used on builder methods (e.g. builder().withField(field) vs builder.field(field) to the one configured in Lombok.
    0 讨论(0)
  • 2020-12-25 13:55

    By referencing answer by Joseph K. Strauss I came up with following solution.

    Plain lombok annotations that worked out for me looks like this. Following annotations give you immutable classes with builder that can be serialized and deserialized by Jackson.

        @Data
        @Setter(AccessLevel.NONE)
        @Builder(toBuilder = true)
        @AllArgsConstructor
        @NoArgsConstructor(access = AccessLevel.PRIVATE)
        public class Clazz {
            private String field;
        } 
    

    I prefer this solution because it requires no additional Jackson specific annotations and no additional lombok specific files

    0 讨论(0)
提交回复
热议问题