使用生成器时无法执行自定义反序列化

时间:2020-04-25 00:01:27

标签: java jackson lombok

我遇到从外部源接收到布尔值(字符串“ 0”或“ 1”)的情况。 映射时,Jackson不会对此进行娱乐,并引发以下错误:

InvalidFormatException:无法反序列化类型boolean的值 来自字符串“ 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:问题 反序列化属性“ bool”(预期类型:[简单类型,类 java.lang.String];实际类型:java.lang.Boolean),问题: [来源:(String)“ {” bool“:” 1“}”处的参数类型不匹配;行:1 栏:9](通过参考链: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:无法 从字符串“ 1”反序列化类型boolean的值:仅“ true”或 在[来源:(String)“ {” bool“:” 1“}”处识别为“ false”;行:1 栏:9](通过参考链: a.a.a.MyClass $ MyClassBuilder [“ bool”])

1 个答案:

答案 0 :(得分:1)

更新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认识到构建器已经存在一个类定义,并且仅为您未手动实现的方法生成代码。