Dav*_*vid 5 jackson lombok jackson2 jackson-databind
我正在寻找有关 Jackson 如何与不可变类型的私有构造函数一起工作的文档。使用 Jackson 2.9.6 和 spring boot 提供的默认对象映射器 2 运行 jdk-10.0.1
给定 JSON:
{"a":"test"}
Run Code Online (Sandbox Code Playgroud)
并给出一个类,如:
public class ExampleValue {
private final String a;
private ExampleValue() {
this.a = null;
}
public String getA() {
return this.a;
}
}
Run Code Online (Sandbox Code Playgroud)
反序列化(令人惊讶的是,至少对我而言)似乎有效。
而这不会:
public class ExampleValue {
private final String a;
private ExampleValue(final String a) {
this.a = a;
}
public String getA() {
return this.a;
}
}
Run Code Online (Sandbox Code Playgroud)
这样做:
public class ExampleValue {
private final String a;
@java.beans.ConstructorProperties({"a"})
private ExampleValue(final String a) {
this.a = a;
}
public String getA() {
return this.a;
}
}
Run Code Online (Sandbox Code Playgroud)
我的假设是,第一个示例可以工作的唯一方法是使用反射来设置最终字段的值(我认为它是由java.lang.reflect.AccessibleObject.setAccessible(true).
问题 1:我对杰克逊在这种情况下的工作方式是否正确?我认为这有可能在不允许此操作的安全管理器下失败?
因此,我个人的偏好是上面的最后一个代码示例,因为它涉及较少的“魔法”并且在安全管理器下工作。但是,我对我发现的有关 Lombok 和构造函数生成的各种线程感到有些困惑,这些线程过去默认生成,@java.beans.ConstructorProperties(...)但后来将默认值更改为不再执行此操作,现在允许人们选择使用lombok.anyConstructor.addConstructorProperties=true
有些人(包括在 lombok发行说明中v1.16.20)建议:
随着 JDK9 的发布,Oracle 或多或少破坏了这个注释,因此需要进行这种破坏性更改。
但我不太清楚这是什么意思,Oracle 破坏了什么?对于我在 jackson 2.9.6 上使用 JDK 10 似乎可以正常工作。
问题 2:有没有人能够解释一下这个注解在 JDK 9 中是如何被破坏的,以及为什么 lombok 现在认为默认情况下不再生成这个注解是不可取的。
答案 1:这正是它的工作原理(也出乎我的意料)。按照上映射杰克逊文档功能,性能INFER_PROPERTY_MUTATORS,ALLOW_FINAL_FIELDS_AS_MUTATORS以及CAN_OVERRIDE_ACCESS_MODIFIERS所有的默认true。因此,在你的第一个例子中,杰克逊
AccessibleObject#setAccessible( CAN_OVERRIDE_ACCESS_MODIFIERS)的帮助下,使用私有构造函数创建一个实例,INFER_PROPERTY_MUTATORS),final的领域,由于ALLOW_FINAL_FIELDS_AS_MUTATORS和AccessibleObject#setAccessible( CAN_OVERRIDE_ACCESS_MODIFIERS)访问该字段。但是,我同意人们不应该依赖它,因为正如您所说,安全经理可以禁止它,或者 Jackson 的默认设置可能会改变。此外,我觉得“不对”,因为我希望该类是不可变的,而该字段是不可设置的。
示例 2 不起作用,因为 Jackson 找不到可用的构造函数(因为它无法将字段名称映射到唯一现有构造函数的参数名称,因为这些名称在运行时不存在)。@java.beans.ConstructorProperties在你的第三个例子中绕过了这个问题,因为杰克逊在运行时明确地寻找那个注释。
答案 2:
我的解释是这@java.beans.ConstructorProperties并没有真正被破坏,只是不能假设 Java 9+ 不再存在。这是由于它在java.desktop模块中的成员资格(例如,请参阅此线程以了解有关此主题的讨论)。由于模块化的 Java 应用程序可能有一个没有这个模块的模块路径,如果 lombok 默认生成这个注解,就会破坏这些应用程序。(此外,此注释在 Android SDK 上一般不可用。)
因此,如果您有非模块化应用程序或java.desktop模块路径上的模块化应用程序,那么让 lombok 通过设置生成注释是完全没问题的lombok.anyConstructor.addConstructorProperties=true,或者如果您不使用 lombok,则手动添加注释。
| 归档时间: |
|
| 查看次数: |
997 次 |
| 最近记录: |