如何使用 Java 验证 yaml?如果 yaml 中缺少一个键?

问题描述

在读取 yaml 时如果丢失了一个密钥如何验证? 读取yaml的API是snakeYaml

Yaml yaml = new Yaml(new Constructor(config.class));
InputStream in = Files.newInputStream(filepath);
yaml.load(in);

预期的 YAML:

KEY1:
  innerKey1:
    innerKey2: value1
    innerKey3: value2
  innerKey4:value3

在读取 yaml 时如果丢失了一个键如何抛出错误? 读取 yaml 时的示例,如果 innerKey3 被遗漏,如何在不迭代所有键的情况下验证它,因为我们已经为该 yaml 定义了一个 POJO。

输入 yaml:

KEY1:
  innerKey1:
    innerKey2: value1
  innerKey4:value3

预期: 缺少innerKey3

解决方法

默认情况下,load() 方法返回一个 Map 实例,所以如果你提前知道键名,但是遍历嵌套属性并不容易。所以在 yaml.load(in) 之后你可以添加一个断言来检查。

assertTrue(document.containsKey("key_you_know"));

但如果是嵌套对象,则应该定义一些自定义类。

class Key {
   private List<InnerKey> innerKeys; // innerKey1
   private String value4; // equal to your innerKey4
   // getters and setters
}

class InnerKey {
   private String value2; // innerKey2
   private String value3; // innerKey3
   // getters and setters
}

然后做断言

Key key = yaml.load(in);
assertNotNull(key.getValue3());
,

其中一种方法可能是将 YAML 转换为 JSON,然后使用 json 模式验证器来验证该 json。有多个库可以将 yaml 转换为 JSON 请检查此线程以将 yaml 转换为 JSON。 How do I convert from YAML to JSON in Java?

获得 JSON 后,您可以使用任何 json 模式验证器,例如 Networklint/Everit。

,

您需要定义一个 TypeDescription 来实现检查所有字段是否存在的附加逻辑:

public class FieldChecker extends TypeDescription {
    public FieldChecker(Class<? extends Object> cls) {
        super(cls);
    }

    /** This is called during construction for creating a new instance
        of our class. The fields are filled later but we can check here
        whether all fields are there. */
    @Override
    public Object newInstance(Node node) {
        /** our objects will always be constructed from mapping nodes. */
        final MappingNode m = (MappingNode)node;
        /** TypeDescription implements the logic discovering the
            class properties via getProperties() */
        for (Property p : getProperties()) {
            boolean found = false;
            // search for a key with matching name in the mapping
            for (NodeTuple p : m.getValue()) {
                // assume all mapping keys are scalars
                if (((ScalarNode)p.getKeyNode()).getValue().equals(p.getName())) {
                    found = true;
                    break;
                }
            }
            if (!found) {
                throw new ConstructorException(null,null,"missing key: " + p.getName(),node.getStartMark(),null);
            }
        }
        // the fields are filled later by SnakeYAML.
        return getType().newInstance();
    }
}

现在,您需要对输入中要检查字段的每个类使用它:

Yaml yaml = new Yaml(new Constructor(new FieldChecker(config.class),List.of(
        new FieldChecker(other.class),new FieldChecker(another.class),...)));