使用构建器时无法执行自定义反序列化
Unable to perform custom deserialisation when using a builder
我有一种情况,我从外部源接收到一个布尔值,作为字符串“0”或“1”。
映射时,杰克逊不接受这一点并抛出以下错误:
InvalidFormatException: Cannot deserialize value of type boolean
from String "1"
因此我正在执行以下有效的自定义反序列化。
在没有构建器的情况下完成的工作示例
@Getter
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
// many other fields
}
class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return "1".equals(parser.getText());
}
}
但我需要这个来与构建器一起工作并按如下方式编写。这不再有效。它抛出与上面相同的错误。
有没有办法让构建器使用自定义反序列化?请注意,除非根本不可能,否则我想坚持使用 Lombok 的 Builder。谢谢。
与建筑商打交道时失败的例子。 (我想修复它以使其正常工作)
@Getter
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
@Builder
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
// many other fields
}
class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return "1".equals(parser.getText());
}
}
快速测试用例,如果您愿意,可以对此进行测试。
public class ATest {
@Test
public void myTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
// test passes if MyClass doesn't use builder.
MyClass myClass = mapper.readValue("{\"bool\":\"1\"}", MyClass.class);
assertTrue(myClass.isBool());
}
}
编辑:根据以下答案尝试建议的选项
选项 1:
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
// many other fields
@JsonSetter
private void setBool(String value){
this.bool = "1".equals(value);
}
}
class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return !"0".equals(parser.getText());
}
}
出现以下错误:
com.fasterxml.jackson.databind.JsonMappingException: Problem
deserializing property 'bool' (expected type: [simple type, class
java.lang.String]; actual type: java.lang.Boolean
), problem:
argument type mismatch at [Source: (String)"{"bool":"1"}"; line: 1,
column: 9] (through reference chain: a.a.a.MyClass["bool"])
选项 2:
@Getter
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
}
出现以下错误:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot
deserialize value of type boolean
from String "1": only "true" or
"false" recognized at [Source: (String)"{"bool":"1"}"; line: 1,
column: 9] (through reference chain:
a.a.a.MyClass$MyClassBuilder["bool"])
2020-11-03 更新:Lombok 1.18.16 发布。
从 Lombok 1.18.16 开始,您可以使用 @Jacksonized
自动生成 Jackson 使用 Lombok 所需的一切 @(Super)Builder
:
@Getter
@Jacksonized
@Builder
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
private boolean bool;
// many other fields
}
对于早期的 Lombok 版本,您必须自定义构建器,以便将注释添加到构建器的 setter 方法。在您的情况下,它的工作原理如下:
@Getter
@Builder
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
public class MyClass {
private boolean bool;
// many other fields
public static class MyClassBuilder {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
public MyClassBuilder bool(boolean bool) {
this.bool = bool;
return this;
}
}
}
Lombok 识别出构建器已经有一个 class 定义,并且只为您没有手动实现的方法生成代码。
我有一种情况,我从外部源接收到一个布尔值,作为字符串“0”或“1”。 映射时,杰克逊不接受这一点并抛出以下错误:
InvalidFormatException: Cannot deserialize value of type
boolean
from String "1"
因此我正在执行以下有效的自定义反序列化。
在没有构建器的情况下完成的工作示例
@Getter
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
// many other fields
}
class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return "1".equals(parser.getText());
}
}
但我需要这个来与构建器一起工作并按如下方式编写。这不再有效。它抛出与上面相同的错误。 有没有办法让构建器使用自定义反序列化?请注意,除非根本不可能,否则我想坚持使用 Lombok 的 Builder。谢谢。
与建筑商打交道时失败的例子。 (我想修复它以使其正常工作)
@Getter
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
@Builder
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
// many other fields
}
class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return "1".equals(parser.getText());
}
}
快速测试用例,如果您愿意,可以对此进行测试。
public class ATest {
@Test
public void myTest() throws IOException {
ObjectMapper mapper = new ObjectMapper();
// test passes if MyClass doesn't use builder.
MyClass myClass = mapper.readValue("{\"bool\":\"1\"}", MyClass.class);
assertTrue(myClass.isBool());
}
}
编辑:根据以下答案尝试建议的选项
选项 1:
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
// many other fields
@JsonSetter
private void setBool(String value){
this.bool = "1".equals(value);
}
}
class NumericBooleanDeserializer extends JsonDeserializer<Boolean> {
@Override
public Boolean deserialize(JsonParser parser, DeserializationContext context) throws IOException {
return !"0".equals(parser.getText());
}
}
出现以下错误:
com.fasterxml.jackson.databind.JsonMappingException: Problem deserializing property 'bool' (expected type: [simple type, class java.lang.String]; actual type:
java.lang.Boolean
), problem: argument type mismatch at [Source: (String)"{"bool":"1"}"; line: 1, column: 9] (through reference chain: a.a.a.MyClass["bool"])
选项 2:
@Getter
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
private boolean bool;
}
出现以下错误:
com.fasterxml.jackson.databind.exc.InvalidFormatException: Cannot deserialize value of type
boolean
from String "1": only "true" or "false" recognized at [Source: (String)"{"bool":"1"}"; line: 1, column: 9] (through reference chain: a.a.a.MyClass$MyClassBuilder["bool"])
2020-11-03 更新:Lombok 1.18.16 发布。
从 Lombok 1.18.16 开始,您可以使用 @Jacksonized
自动生成 Jackson 使用 Lombok 所需的一切 @(Super)Builder
:
@Getter
@Jacksonized
@Builder
public class MyClass {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
private boolean bool;
// many other fields
}
对于早期的 Lombok 版本,您必须自定义构建器,以便将注释添加到构建器的 setter 方法。在您的情况下,它的工作原理如下:
@Getter
@Builder
@JsonDeserialize(builder = MyClass.MyClassBuilder.class)
public class MyClass {
private boolean bool;
// many other fields
public static class MyClassBuilder {
@JsonDeserialize(using = NumericBooleanDeserializer.class)
@JsonProperty("bool")
public MyClassBuilder bool(boolean bool) {
this.bool = bool;
return this;
}
}
}
Lombok 识别出构建器已经有一个 class 定义,并且只为您没有手动实现的方法生成代码。