Handling Missing Fields with SnakeYaml

Suppose I have a simple class with two fields, getters and setters. I want to sometimes serialize and deserialize objects of this class.

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);
    }
}

      

I want the code in the main method to throw an exception because the doc

field is missing a

. Unfortunately, this doesn't work by default.

Can I configure SnakeYaml for this?

+3


source to share


1 answer


Using the builder pattern is probably the best approach. Putting it all together made it easier for him to do it with Jackson (not sure if he / doesn't handle SnakeYaml on its own) and Immutables ( https://immutables.github.io/ ) for the builder.

Note that you can write the creator yourself and you can do the validation in the build()

builder method , but Immutables makes it all a little easier.

First, your model class:

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

      

Note that getA()

it cannot return null by default (you could annotate it with, @Nullable

or do it Optional<String>

if you want to change this behavior). After starting the annotation processor, you will have a class ImmutableFoo

with a constructor with the desired semantics.



Then switch your de-serialization to use Jackson (which SnakeYaml apparently uses under the hood, so it shouldn't be super different):

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

      

Now a value will be selected JsonMappingException

whose reason is in the builder:

java.lang.IllegalStateException: Unable to create Foo, some required attributes are not set [a]

If you want to avoid Immutables, you can do such a check in your own developer.

0


source







All Articles