使用SnakeYaml处理缺少的字段

时间:2017-05-02 10:42:35

标签: java serialization deserialization yaml snakeyaml

假设我有一个简单的类,它包含两个字段,getter和setter。我想有时序列化和反序列化这个类的对象。

public class Foo {
    private String a;
    private int b;

    public void setA(String a) {
        System.out.println("a setter called");
        this.a = Objects.requireNonNull(a, "Required non null field.");
    }

    public void setB(int b) {
        System.out.println("b setter called");
        this.b = b;
    }

    public String getA() {
        return a;
    }

    public int getB() {
        return b;
    }

    public static void main(String[] args) {
        Representer representer = new Representer();
        representer.getPropertyUtils().setSkipMissingProperties(false);
        Yaml yaml = new Yaml(new Constructor(), representer);
        String doc = "b: 10";
        Foo testBean = yaml.loadAs(doc, Foo.class);
    }
}

我希望main方法中的代码抛出一些异常,因为a中缺少字段doc。不幸的是,它默认情况下不起作用。

我能以某种方式配置SnakeYaml吗?

1 个答案:

答案 0 :(得分:0)

使用构建器模式可能是最好的方法。把这一切放在一起,最终更容易与杰克逊(不确定它是否可以单独使用SnakeYaml)和不可变(https://immutables.github.io/)为构建者做到这一点。

请注意,您可以自己编写构建器,并且可以在构建器的build()方法中进行验证,但是Immutables可以使它更容易。

首先,您的模型类:

@Value.Immutable
@JsonDeserialize(builder = ImmutableFoo.Builder.class)
public interface Foo {
    String getA();
    int getB();
}

请注意,默认情况下getA()无法返回null(您可以使用@Nullable对其进行注释,或者如果您想要更改该行为,则将其设为Optional<String>。在运行注释处理器之后,您将拥有一个ImmutableFoo类,其中包含具有所需语义的构建器。

然后切换你的反序列化以使用杰克逊(显然在引擎盖下使用SnakeYaml,所以不应该是超级不同):

new ObjectMapper(new YAMLFactory()).readValue("b: 10", Foo.class);

现在抛出一个JsonMappingException,其原因在于构建器:

  

java.lang.IllegalStateException:无法构建Foo,某些必需属性未设置[a]

如果您想避免使用Immutables,可以在自己的构建器中进行此类验证。