我正在尝试合并杰克逊和龙目岛。那是我的课程:
package testelombok;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import lombok.AllArgsConstructor;
import lombok.Value;
import lombok.experimental.Wither;
@Value
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
package testelombok;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.xebia.jacksonlombok.JacksonLombokAnnotationIntrospector;
import java.io.IOException;
public class TestLombok {
public static void main(String[] args) throws IOException {
TestFoo tf = new TestFoo("a", 5);
System.out.println(tf.withX("b"));
ObjectMapper om = new ObjectMapper().setAnnotationIntrospector(new JacksonLombokAnnotationIntrospector());
System.out.println(om.writeValueAsString(tf));
TestFoo tf2 = om.readValue(om.writeValueAsString(tf), TestFoo.class);
System.out.println(tf2);
}
}
这些是我在classpth中添加的JAR:
龙目岛:https://projectlombok.org/downloads/lombok.jar(版本1.16.10)
杰克逊核心:http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-core/2.8.2/jackson-core-2.8.2.jar
Jackson databind:http://repo1.maven.org/maven2/com/fasterxml/jackson/core/jackson-databind/2.8.2/jackson-databind-2.8.2.jar
Jackson-lombok:http://repo1.maven.org/maven2/io/paradoxical/jackson-lombok/1.1/jackson-lombok-1.1.jar
我正在使用Netbeans进行编译(我不认为这是真的相关,但无论如何我都在报告这一点,以使其完美且忠实地再现)。上面的五个JAR保存在项目文件夹中名为“lib
”的文件夹中(以及“src
”,“nbproject
”,“test
”和“{ {1}}“)。我通过项目属性中的“添加JAR /文件夹”按钮将它们添加到Netbeans中,它们按照上面列表的确切顺序列出。该项目是标准的“Java应用程序”类型项目。
此外,Netbeans项目配置为“不在编译时保存”,“生成调试信息”,“报告已弃用的API “,”跟踪java依赖项“,”激活注释处理“和”激活注释在编辑器中处理“。 Netbeans中未明确配置注释处理器或注释处理选项。此外,“build
”命令行选项在编译器命令行中传递,编译器在外部VM上运行。
我的javac版本是1.8.0_72,我的java版本是1.8.0_72-b15。我的Netbeans是8.1。
我的项目编译得很好。但是,它会在执行时抛出异常。例外似乎不是任何容易或明显可修复的东西。这是输出,包括stacktrace:
-Xlint:all
我已经尝试过使用TestFoo(x=b, z=5)
{"z":5,"xoom":"a"}
Exception in thread "main" com.fasterxml.jackson.databind.JsonMappingException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at [Source: {"z":5,"xoom":"a"}; line: 1, column: 1]
at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:296)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:269)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCacheValueDeserializer(DeserializerCache.java:244)
at com.fasterxml.jackson.databind.deser.DeserializerCache.findValueDeserializer(DeserializerCache.java:142)
at com.fasterxml.jackson.databind.DeserializationContext.findRootValueDeserializer(DeserializationContext.java:475)
at com.fasterxml.jackson.databind.ObjectMapper._findRootDeserializer(ObjectMapper.java:3890)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:3785)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:2833)
at testelombok.TestLombok.main(TestLombok.java:14)
Caused by: java.lang.IllegalArgumentException: Argument #0 of constructor [constructor for testelombok.TestFoo, annotations: {interface java.beans.ConstructorProperties=@java.beans.ConstructorProperties(value=[x, z]), interface com.fasterxml.jackson.annotation.JsonCreator=@com.fasterxml.jackson.annotation.JsonCreator(mode=DEFAULT)}] has no property name annotation; must have name when multiple-parameter constructor annotated as Creator
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._addDeserializerConstructors(BasicDeserializerFactory.java:511)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory._constructDefaultValueInstantiator(BasicDeserializerFactory.java:323)
at com.fasterxml.jackson.databind.deser.BasicDeserializerFactory.findValueInstantiator(BasicDeserializerFactory.java:253)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.buildBeanDeserializer(BeanDeserializerFactory.java:219)
at com.fasterxml.jackson.databind.deser.BeanDeserializerFactory.createBeanDeserializer(BeanDeserializerFactory.java:141)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer2(DeserializerCache.java:406)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createDeserializer(DeserializerCache.java:352)
at com.fasterxml.jackson.databind.deser.DeserializerCache._createAndCache2(DeserializerCache.java:264)
... 7 more
和@Value
注释随机戳,但我无法做得更好。
我查看了例外found an old bug report on jackson和another one that is open, but seems to be related to something else。但是,这仍然没有说明这个错误是什么或如何解决它。此外,我找不到任何其他有用的东西。
由于我要做的是lombok和jackson的非常基本的用法,我似乎找不到有关如何解决此问题的更多有用信息似乎很奇怪。也许我错过了什么?
除了说“不使用lombok ”或“不使用jackson ”之外,有人知道如何解决这个问题吗?
答案 0 :(得分:26)
如果你想使用lombok和jackson的不可变但是json可序列化的POJO。
在lomboks构建器@JsonPOJOBuilder(withPrefix = "")
上使用jacksons new注释
我试过这个解决方案,效果很好。
样本用法
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Value;
@JsonDeserialize(builder = Detail.DetailBuilder.class)
@Value
@Builder
public class Detail {
private String url;
private String userName;
private String password;
private String scope;
@JsonPOJOBuilder(withPrefix = "")
public static class DetailBuilder {
}
}
如果您的@Builder
课程太多,并且您不希望样板代码为空注释,则可以覆盖注释拦截器以使其为空withPrefix
mapper.setAnnotationIntrospector(new JacksonAnnotationIntrospector() {
@Override
public JsonPOJOBuilder.Value findPOJOBuilderConfig(AnnotatedClass ac) {
if (ac.hasAnnotation(JsonPOJOBuilder.class)) {//If no annotation present use default as empty prefix
return super.findPOJOBuilderConfig(ac);
}
return new JsonPOJOBuilder.Value("build", "");
}
});
您可以使用@JsonPOJOBuilder
注释删除空的构建器类。
答案 1 :(得分:5)
我有完全相同的问题,通过添加suppressConstructorProperties = true
参数“解决”它(使用您的示例):
@Value
@Wither
@AllArgsConstructor(suppressConstructorProperties = true)
public class TestFoo {
@JsonProperty("xoom")
private String x;
private int z;
}
杰克逊显然不喜欢为构造函数添加java.beans.ConstructorProperties
注释。 suppressConstructorProperties = true
参数告诉Lombok不要添加它(默认情况下会这样做)。
答案 2 :(得分:4)
如果您想将 @Builder
与 Jackson 一起使用,我找到了两种方法来解决此问题。
选项 1
@Builder
@Getter
@Setter
@JsonIgnoreProperties(ignoreUnknown = true)
@AllArgsConstructor(access = AccessLevel.PRIVATE)
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Person {
@JsonProperty("user_name")
private String name;
}
选项 2
感谢 this 篇文章。
Jackson 期望构建器方法像 .withProperty(...)
一样开始,但 Lombok 生成 .property(...)
。
您可以做的是自己创建构建器类,以便您可以向其中添加 Jackson 注释。然后 Lombok 将重新使用该类并将所有构建器方法添加到其中。
@JsonDeserialize(builder = MyDto.MyDtoBuilder.class)
@Builder
@Getter
public class MyDto {
@JsonProperty("user_id")
private String userId;
@JsonPOJOBuilder(withPrefix = "")
@JsonIgnoreProperties(ignoreUnknown = true)
public static class MyDtoBuilder {
}
}
@JsonIgnorePropertie
之类的其他属性会用于构建器另一个缺点是重构不会自动重命名 MyDtoBuilder
。我希望在未来的 Lombok/Jackson 版本中可以解决这个问题。
更新:我找到了另一个解决方案(用 lombok 1.18.20 和 spring boot 2.4.5 测试),作为选项 1 添加。
答案 3 :(得分:4)
lombok.anyConstructor.suppressConstructorProperties=true
已弃用。定义@Value
(https://projectlombok.org/features/configuration)并将POJO的lombok注释从@Data
更改为@NoArgsConstructor
+ @AllArgsConstructor
+ # Compute the XOR of all numbers from 0 to |A| - 1 and all entries in A
# Assume A is a list of integers
miss_XOR_dup = functools.reduce(lambda v, i: v ^ i[0] ^ i[1], enumerate(A), 0)
适用于我。
答案 4 :(得分:2)
我尝试了以上几种方法,而且都很气质。 对我真正有用的是我找到的here答案。
在项目的根目录中添加一个文件(如果尚未完成的话)
lombok.config
并在其中粘贴
lombok.anyConstructor.addConstructorProperties=true
然后,您可以按以下方式定义pojos:
@Data
@AllArgsConstructor
public class MyPojo {
@JsonProperty("Description")
private String description;
@JsonProperty("ErrorCode")
private String errorCode;
}
答案 5 :(得分:2)
我建议您使用 Gson,因为它不会给您带来所有这些麻烦。
我在 Spring Boot 应用程序中添加了这个
# Build a small Pixel CNN++ model to train on MNIST.
import tensorflow as tf
import tensorflow_datasets as tfds
import tensorflow_probability as tfp
tfd = tfp.distributions
tfk = tf.keras
tfkl = tf.keras.layers
tf.enable_v2_behavior()
# Load MNIST from tensorflow_datasets
data = tfds.load('mnist')
train_data, test_data = data['train'], data['test']
def image_preprocess(x):
x['image'] = tf.cast(x['image'], tf.float32)
return (x['image'],) # (input, output) of the model
batch_size = 16
train_it = train_data.map(image_preprocess).batch(batch_size).shuffle(1000)
image_shape = (28, 28, 1)
# Define a Pixel CNN network
dist = tfd.PixelCNN(
image_shape=image_shape,
num_resnet=1,
num_hierarchies=2,
num_filters=32,
num_logistic_mix=5,
dropout_p=.3,
)
# Define the model input
image_input = tfkl.Input(shape=image_shape)
# Define the log likelihood for the loss fn
log_prob = dist.log_prob(image_input)
# Define the model
model = tfk.Model(inputs=image_input, outputs=log_prob)
model.add_loss(-tf.reduce_mean(log_prob))
# Compile and train the model
model.compile(
optimizer=tfk.optimizers.Adam(.001),
metrics=[])
model.fit(train_it, epochs=10, verbose=True)
# sample five images from the trained model
samples = dist.sample(5)
连同maven中的依赖,我解决了所有问题。我不需要修改我的 lombok 注释 pojo
答案 6 :(得分:2)
对我来说,当我将lombok版本更新为: 'org.projectlombok:lombok:1.18.0'
答案 7 :(得分:1)
你也需要这个模块。 https://github.com/FasterXML/jackson-modules-java8
然后打开编译器的-parameters标志。
<build>
<pluginManagement>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.7.0</version>
<configuration>
<compilerArgs>
<arg>-parameters</arg>
</compilerArgs>
</configuration>
</plugin>
答案 8 :(得分:1)
不可变+龙目岛+杰克逊可以通过以下方式实现:
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
import lombok.NoArgsConstructor;
import lombok.Value;
@Value
@NoArgsConstructor(force = true, access = AccessLevel.PRIVATE)
@AllArgsConstructor
public class LocationDto {
double longitude;
double latitude;
}
class ImmutableWithLombok {
public static void main(String[] args) throws Exception {
ObjectMapper objectMapper = new ObjectMapper();
String stringJsonRepresentation = objectMapper.writeValueAsString(new LocationDto(22.11, 33.33));
System.out.println(stringJsonRepresentation);
LocationDto locationDto = objectMapper.readValue(stringJsonRepresentation, LocationDto.class);
System.out.println(locationDto);
}
}
答案 9 :(得分:1)
如果使用"mixin" pattern,你可以让杰克逊玩几乎任何东西。基本上,它为您提供了一种方法,可以将Jackson注释添加到现有类中,而无需实际修改该类。我倾向于在这里推荐它而不是Lombok解决方案,因为这解决了杰克逊在Jackson功能方面遇到的问题,因此它更有可能长期工作。
答案 10 :(得分:1)
从lombok 1.18.4开始,您可以配置将哪些注释复制到 构造函数参数。将其插入您的
lombok.config
:lombok.copyableAnnotations += com.fasterxml.jackson.annotation.JsonProperty
然后将
@JsonProperty
添加到您的字段中:...
即使名称匹配,在每个字段上都需要一个@JsonProperty,但这还是一个很好的习惯。您还可以使用此方法将字段设置为public final,我更喜欢使用getter。
@ToString
@EqualsAndHashCode
@Wither
@AllArgsConstructor(onConstructor=@__(@JsonCreator))
public class TestFoo {
@JsonProperty("xoom")
private final String x;
@JsonProperty("z")
private final int z;
}
答案 11 :(得分:1)
它可以做得更简单,不需要额外的注释,问题可能出在继承上,即子类也应该是可反序列化的。所以,我的例子:
要求:
lombok.config
在项目根目录中,正文包含:
lombok.anyConstructor.addConstructorProperties=true
/** The parent class **/
@Value
@NonFinal
@SuperBuilder
@RequiredArgsConstructor
public class Animal {
String name;
}
/** The child class **/
@Value
@SuperBuilder
@RequiredArgsConstructor
public class Cat {
Long tailLength;
@ConstructorProperties({"tailLength", "name})
public Cat(Long tailLength, String name) {
super(name);
this.tailLength = tailLength;
}
}
它:
ObjectMapper
和 Jackson 进行序列化/反序列化我对其他例子的建议:
Jackson
注释,当 Jackson 能够在没有任何注释的情况下进行序列化/反序列化时,它会产生耦合。@AllArgsConstructor
用于不可变实体。当您的类只有 final 字段时,概念上正确的是 @RequiredArgsConstructor
,这就是您保证类客户端始终仅依赖具有不可变实体的构造函数的方式。 @AllArgsConstructor
是否会导致传递空值。答案 12 :(得分:0)
我遇到了让Lombok不添加ConstructorProperies
注释的问题,所以走了另一条道路并禁止杰克逊查看该注释。
罪魁祸首是JacksonAnnotationIntrospector.findCreatorAnnotation。注意:
if (_cfgConstructorPropertiesImpliesCreator
&& config.isEnabled(MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES)
另请注意JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator:
public JacksonAnnotationIntrospector setConstructorPropertiesImpliesCreator(boolean b)
{
_cfgConstructorPropertiesImpliesCreator = b;
return this;
}
这两个选项,要么将MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
设置为false,要么将JacksonAnnotationIntrospector
设置setConstructorPropertiesImpliesCreator
设置为false
,并将此AnnotationIntrospector
设置为ObjectMapper
通过ObjectMapper.setAnnotationIntrospector。
注意一些事情,我使用的是Jackson 2.8.10,并且该版本MapperFeature.INFER_CREATOR_FROM_CONSTRUCTOR_PROPERTIES
不存在。我不确定它添加了哪个版本的Jackson。因此,如果不存在,请使用JacksonAnnotationIntrospector.setConstructorPropertiesImpliesCreator
机制。
答案 13 :(得分:0)
我也为此挣扎了一下。但是请仔细阅读文档here 我可以看到onConstructor批注参数被认为是实验性的,并且在我的IDE(STS 4)上不受很好的支持。根据Jackson的文档,默认情况下,不对私人成员进行反序列化。有快速的方法可以解决此问题。
添加JsonAutoDetect批注并适当地设置它以检测受保护/私有成员。这对于DTO来说很方便
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)
public class SomeClass
添加带有@JsonCreator批注的工厂函数,如果您需要一些对象验证或其他转换,则此方法效果最佳。
public class SomeClass {
// some code here
@JsonCreator
public static SomeClass factory(/* params here dressing them in @JsonProperty annotations*/) {
return new SomeClass();
}
}
当然,您也可以手动在自己中添加构造函数。
答案 14 :(得分:0)
尝试添加@NoArgsConstructor
答案 15 :(得分:0)
我有一个不同的问题,那就是布尔基本类型。
private boolean isAggregate;
其结果是引发以下错误
Exception: Unrecognized field "isAggregate" (class
Lambok作为吸气剂将isAggregate
转换为isAggregate()
,使该属性在内部以aggregate
而不是isAggregate
的身份进入lombok。 Jackson库不喜欢它,它需要isAggregate
属性。
我将原始布尔值更新为Wrapper布尔值,以解决此问题。如果要处理boolean
类型,还有其他选择,请参见下面的参考。
Sol:
private Boolean isAggregate;
答案 16 :(得分:0)
For i As Integer = 0 To itemlist.Count
Dim item = itemlist.Item(i);
If item.Innerhtml = "Controller" Then
MsgBox(item.innertext)
Dim iNext = i++;
if iNext <= itemList.Count Then
Dim closestItem = itemList.Item(iNext)
'Do things
End If
Exit For
End If
Next
除了Data Class之外,它应该正确配置ObjectMapper。 在这种情况下,它可以正常使用ParameterNamesModule配置,并设置Fields和Creator Methods的可见性
@JsonInclude(JsonInclude.Include.NON_NULL)
@Data
public class Person {
String id;
String first;
String last;
}
然后它应该按预期工作。
答案 17 :(得分:0)
对我有用的选项
答案 18 :(得分:0)
我的所有课程都注释如下:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
至少在几年内它与所有Lombok和Jackson版本一起使用。
示例:
@JsonAutoDetect(fieldVisibility = Visibility.ANY)
@JsonInclude(JsonInclude.Include.NON_DEFAULT)
@Data
@Accessors(fluent = true)
@NoArgsConstructor
@AllArgsConstructor
public class Person {
String id;
String first;
String last;
}
就是这样。 龙目岛和杰克逊一起玩耍就像一个魅力。
答案 19 :(得分:0)
我设法保持我的类不可变,并通过使用这个 lombok 注释反序列化它们:
{{1}}