非Spring、非SpringBoot 環境で、YAMLを読む

Spring や SpringBoot を使わない環境で YAML を読込むのにどうしようという課題で、
snakeyaml を使うのが簡単です。
( SpringBoot も結局は、snakeyaml を使っているので、Spring起動時のあの重たい起動の一部で、YAML読込みで使用されているので
安心して使えるのですが。結構古いのかも。)
https://bitbucket.org/asomov/snakeyaml/wiki/Documentation

インスタンスを生成したら、loadAs メソッドで読込ませたいクラスを指定して読み込ませます。

try(InputStream in=ClassLoader.getSystemClassLoader().getResourceAsStream("sample.yml")){
   Yaml yaml = new Yaml();
   Sample sample = yaml.loadAs(in, Sample.class);

}catch(IOException e){
   e.printStackTrace();
}

snakeyaml は、そのまま使うと日付時刻は java.util.Date への変換になってしまいます。
これに対する解は、以下にのってます。
https://bitbucket.org/asomov/snakeyaml/issues/419/add-native-support-for-parsing-serializing
これだけだと、中途半端なので、
以下のように、Yaml生成時に、LocalDate , LocalDateTime 変換用コンストラク
(org.yaml.snakeyaml.constructor.Constructor)
で、書式を指定できるように、以下のようにクラスを用意します。

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.yaml.snakeyaml.constructor.Constructor;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.NodeId;
import org.yaml.snakeyaml.nodes.ScalarNode;
import org.yaml.snakeyaml.nodes.Tag;

public final class LocalDateYamlConstructor extends Constructor{
   private DateTimeFormatter datetimeformatter;
   private DateTimeFormatter dateformatter;

   public LocalDateYamlConstructor(){
      datetimeformatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
      dateformatter = DateTimeFormatter.ISO_LOCAL_DATE;
      this.yamlClassConstructors.put(NodeId.scalar, new LocalDateTimeConstructor());
   }

   public LocalDateYamlConstructor addLocalDateTimeFormat(String format) {
      this.datetimeformatter = DateTimeFormatter.ofPattern(format);
      return this;
   }
   public LocalDateYamlConstructor addLocalDateFormat(String format) {
      this.dateformatter = DateTimeFormatter.ofPattern(format);
      return this;
   }

   private class LocalDateTimeConstructor  extends ConstructScalar  {
      @Override
      public Object construct(Node node) {
         if (node.getTag().equals(Tag.TIMESTAMP)){
            if (node.getType().equals(LocalDate.class)) {
               return LocalDate.parse(((ScalarNode)node).getValue(), dateformatter);
            }else{
               return LocalDateTime.parse(((ScalarNode)node).getValue(), datetimeformatter);
            }
         }else if(node.getTag().equals(Tag.STR) && node.getType().equals(LocalDate.class)){
            return LocalDate.parse(((ScalarNode)node).getValue(), dateformatter);
         }else if(node.getTag().equals(Tag.STR) && node.getType().equals(LocalDateTime.class)){
            return LocalDateTime.parse(((ScalarNode)node).getValue(), datetimeformatter);
         }else{
            return super.construct(node);
         }
      }
   }
}

Yaml インスタンス生成時に、これを指定します。

Yaml yaml = new Yaml(
   new LocalDateYamlConstructor()
   .addLocalDateTimeFormat("yyyy/MM/dd HH:mm:ss")
   .addLocalDateFormat("yyyy/MM/dd")
);
Sample sample = yaml.loadAs(in, Sample.class);