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
Immutable Lombok annotated class with Hymanson
提问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.config
file in an appropriate locationwith the line:lombok.anyConstructor.addConstructorProperties = true
- Add lombok
@Value
annotation 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:
这种方法:
- meets the criteria
- has less boilerplace than the previous top answer
- works on v1.16.20 (January 9th, 2018)and later
- 符合条件
- 比之前的最佳答案有更少的样板
- 适用于v1.16.20(2018 年 1 月 9 日)及更高版本
回答by Thomas Fritsch
You can use Lombok's @Builder
annotation 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 生成的构建器有点棘手。
- You need to annotate your POJO class with
@JsonDeserialize(builder = ...)
to tell Hymanson which is the builder class to use. - You need to annotate the builder class with
@JsonPOJOBuilder(withPrefix = "")
to tell Hymanson that its setter-methods do notstart withwith
.
- 您需要注释您的 POJO 类
@JsonDeserialize(builder = ...)
以告诉 Hymanson 哪个是要使用的构建器类。 - 您需要注释 builder 类
@JsonPOJOBuilder(withPrefix = "")
以告诉 Hymanson 它的 setter-methods不以with
.
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
}
}
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>