java 与 Jackson 的不可变 Lombok 注释类

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/49999492/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-03 19:22:53  来源:igfitidea点击:

Immutable Lombok annotated class with Hymanson

javajsonHymansonlombokHymanson-databind

提问by Christian Neverdal

What is the preferred way to create class that is

创建类的首选方法是什么

  • Immutable
  • Can be serialized/deserialized with Hymanson
  • Human-readable and with low level of boilerplate
  • 不可变
  • 可以使用 Hymanson 进行序列化/反序列化
  • 人类可读和低水平的样板

Preferably, I would have liked something like this to work:

最好,我会喜欢这样的工作:

@Data(onConstructor = @__(@JsonCreator))

and then have all fields to be private final. However, this does not even compile (and I'm not sure why). Using

然后将所有字段设为private final. 但是,这甚至无法编译(我不确定为什么)。使用

@AllArgsConstructor(onConstructor = @__(@JsonCreator))

will compile but only yields

将编译但只产生

InvalidDefinitionException: No serializer found for class

回答by robSE13

add ConstructorProperties:

添加构造函数

  • Create a lombok.configfile in an appropriate locationwith the line: lombok.anyConstructor.addConstructorProperties = true
  • Add lombok @Valueannotation to your class to make it immutable
  • 使用以下行在适当的位置创建一个lombok.config文件: lombok.anyConstructor.addConstructorProperties = true
  • 将 lombok@Value注释添加到您的类中以使其不可变

Then serialization and deserialization by Hymanson works as expected.

然后Hyman逊的序列化和反序列化按预期工作。

This method:

这种方法:

回答by Thomas Fritsch

You can use Lombok's @Builderannotation to generate a builder for your immutable POJO class. But making the Lombok-generated builder usable by Hymanson's deserialization is somewhat tricky.

您可以使用 Lombok 的@Builder注释为不可变 POJO 类生成构建器。但是让Hyman逊的反序列化可以使用 Lombok 生成的构建器有点棘手。

Example:

例子:

An immutable POJO class:

一个不可变的 POJO 类:

@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
    }
}

POJO outline

POJO大纲

Here is a JUnit test to verify the serialization/deserialization:

这是一个用于验证序列化/反序列化的 JUnit 测试:

public class PointTest extends Assert {

    private ObjectMapper objectMapper = new ObjectMapper();

    @Test
    public void testSerialize() throws IOException {
        Point point = new Point(10, 20);
        String json = objectMapper.writeValueAsString(point);
        assertEquals("{\"x\":10,\"y\":20}", json);
    }

    @Test
    public void testDeserialize() throws IOException {
        String json = "{\"x\":10,\"y\":20}";
        Point point = objectMapper.readValue(json, Point.class);
        assertEquals(new Point(10, 20), point);
    }
}

回答by Joseph K. Strauss

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.

当然,您仍然可以有一些直接修改字段的私有方法,但是在@Data POJO 中甚至不太可能有任何实际代码,因此希望不会发生这种情况。

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:

免责声明:这将产生不让常规 Java 代码创建对象的副作用(可能是有益的),因为只有一个没有修改器的默认构造函数。为了允许正常构建,您还需要 2 个注释:

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

回答by Streamline27

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

通过参考Joseph K. Strauss 的回答,我想出了以下解决方案。

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 Hymanson.

对我有用的普通 lombok 注释看起来像这样。以下注释为您提供了带有构建器的不可变类,可以由 Hymanson 序列化和反序列化。

    @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 Hymanson specific annotationsand no additional lombok specific files

我更喜欢这个解决方案,因为它不需要额外的Hymanson 特定注释,也不需要额外的lombok 特定文件

回答by Ajay Mathur

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

在 pom.xml 中添加 Hymanson Dataformat 依赖项后,Thomas Fritsch 的回答与 Spring Boot 完美配合。

@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.Hymanson.dataformat/Hymanson-dataformat-xml -->
<dependency>
    <groupId>com.fasterxml.Hymanson.dataformat</groupId>
    <artifactId>Hymanson-dataformat-xml</artifactId>
</dependency>