【问题标题】:How to validate an yaml using Java? If a key is missed in the yaml?如何使用 Java 验证 yaml?如果 yaml 中缺少密钥?
【发布时间】:2021-06-14 10:16:42
【问题描述】:

在读取 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 时,如果丢失了某个键,如何抛出错误? 如果错过了 innerKey3,则在读取 yaml 时的示例如何在不迭代所有键的情况下验证它,因为我们已经为该 yaml 定义了 POJO。

输入yaml:

KEY1:
  innerKey1:
    innerKey2: value1
  innerKey4:value3

预期: innerKey3 丢失

【问题讨论】:

    标签: java yaml snakeyaml


    【解决方案1】:

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

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

    【讨论】:

      【解决方案2】:

      默认情况下,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());
      

      【讨论】:

      • 默认情况下,load() 方法返回一个 Map 实例,但如果您专门为根类型提供 Constructor,则不会返回,如问题所示。
      【解决方案3】:

      您需要定义一个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), ...)));
      

      【讨论】:

        猜你喜欢
        • 2020-11-13
        • 1970-01-01
        • 1970-01-01
        • 2012-10-31
        • 2019-02-13
        • 1970-01-01
        • 2016-01-04
        • 2022-10-05
        • 2019-02-13
        相关资源
        最近更新 更多