snakeyaml で、オブジェクトからYAMLを作る

非Spring、非SpringBoot 環境で、YAMLを読む - Oboe吹きプログラマの黙示録
を書いたので、今度はJava オブジェクトから、YAML テキストを snakeyaml で出力します。

Yaml yaml = new Yaml();

基本、Yamlインスタンス作って、dumpメソッドで出力するのですが、

String res = yaml.dump(sample);

どうも、これだと、結果テキストの先頭に、"!!"の2文字に続けて、sample のクラス名の1行が先頭に
出力される。
さらに、YAML形式といっても、リストは1行で収まる書式にされている。
ダンプ例)

!!org.aaa.dto.Sample
address:
  clist: [21, 22, 23]
  group: {info1: A, info2: B}
ate: {date: 2020/09/21, datetime: '2020/09/22 11:09:22'}

snakeyaml では、Java オブジェクトから YAML 生成を目的にはしていないんじゃないかと思われる。
YAML書式になるようにダンプするなら、dumpAs メソッドでオプション指定で出力する。
  dumpAs( object, org.yaml.snakeyaml.nodes.Tag , DumperOptions.FlowStyle )
ということらしい。
2番目の引数を、Tag.YAML として実行すると、
先頭の行が、"!!yaml" として出力される。

String res = yaml.dumpAs(sample, Tag.YAML, DumperOptions.FlowStyle.BLOCK);

Tag.YAML の代わりに、null を指定すれば、"!!"の2文字に続けて、sample のクラス名になる。
FlowStyle.BLOCK を指定すれば、見慣れたYAML書式が出力される。

!!yaml
address:
  clist:
  - 21
  - 22
  - 23
  group:
    info1: A
    info2: B
ate:
  date: 2020/09/21
  datetime: 2020/09/22 11:09:22

どうも、この 先頭行 "!!" 出力させない方法がわからない!
日付、時刻を出力でも java.time.* では、書く必要があり、
非Spring、非SpringBoot 環境で、YAMLを読む - Oboe吹きプログラマの黙示録
と同様、出力用の変換クラスが必要である。
Yaml のコンストラク
  public Yaml(BaseConstructor constructor, Representer representer)
を使用すれば、YAML読込みも、出力も使用できる Yamlインスタンスになる。
この Representer representer として、java.time の LocalDate と LocalDateTime 変換用を用意すれば良い。

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import org.yaml.snakeyaml.nodes.Node;
import org.yaml.snakeyaml.nodes.Tag;
import org.yaml.snakeyaml.representer.Representer;

public class LocalDateRepresenter extends Representer{
   private DateTimeFormatter dateformatter;
   private DateTimeFormatter datetimeformatter;
   private Tag dateTag;
   private Tag datetimeTag;

   public LocalDateRepresenter(){
      dateTag = Tag.TIMESTAMP;
      datetimeTag = Tag.TIMESTAMP;
      dateformatter = DateTimeFormatter.ISO_LOCAL_DATE;
      datetimeformatter = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
      multiRepresenters.put(LocalDate.class, new RepresentLocalDate());
      multiRepresenters.put(LocalDateTime.class, new RepresentLocalDateTime());
   }
   public LocalDateRepresenter addLocalDateTimeFormat(String format) {
      this.datetimeformatter = DateTimeFormatter.ofPattern(format);
      this.datetimeTag = Tag.STR;
      return this;
   }
   public LocalDateRepresenter addLocalDateFormat(String format) {
      this.dateformatter = DateTimeFormatter.ofPattern(format);
      this.dateTag = Tag.STR;
      return this;
   }
   private class RepresentLocalDate extends RepresentDate {
      @Override
      public Node representData(Object obj){
         LocalDate localDateTime = (LocalDate)obj;
         String date = localDateTime.format(dateformatter);
         return representScalar(getTag(obj.getClass(), dateTag), date);
      }
   }
   private class RepresentLocalDateTime extends RepresentDate {
      @Override
      public Node representData(Object obj){
         LocalDateTime localDateTime = (LocalDateTime)obj;
         String date = localDateTime.format(datetimeformatter);
         return representScalar(getTag(obj.getClass(), datetimeTag), date);
      }
   }
}

ここで注目すべきは、multiRepresenters に、class と、private 定義した RepresentDate 継承クラスを
追加していくことであり、1つの Representer で、複数の型についての
変換仕様を登録できることである。
public interface Represent インターフェースで、
org.yaml.snakeyaml.nodes.Node を返すことを約束したものを定義していく。