SimpleJukeっていうDiscord用のMusicBotを開発しています。
最近それのv0.1.0ができました。
SimpleJukeは設定ファイルにYamlを採用していて
0.8.0まではsnakeYamlを採用していました。
ただこいつがちょっと面倒くさくて、Objectに変換する場合は引数の定義をpublicにするかsetterを配置する必要がありました。
プログラム側から変更を加えることのない設定ファイルなのでSetterは必要なくて、コード量的な意味で考えればpublicにするのがベストなのですが、
v0.1.0から外部モジュール(プラグイン的なやつ)からかなり早い段階で設定クラスにアクセスできるようになりまして、ここで意図しない変更を加えられた場合最悪の場合深刻な問題が生じる可能性がありました。
なので設定クラスは外部から変更できないようにする必要がありました。
一応snakeYamlもMapperを自分で書けばそういった動作もできるようですが、
そもそも定義がprivateでSetterがない状態で値を設定する手段を私は知らないのでライブラリに頼る他ありませんでした。
以前からJsonをJacksonでパースして利用していて、これがそういった挙動をすることは知っていました。
そしてJacksonにはYamlをロードするためのライブラリが有ることも知っていました。
なら、これを使えば実現できるのでは?と考えました。
JacksonでYamlを使うにはCore・Databind・Dataformat-Yamlが必要です。
Mavenの場合はこのように設定すれば大丈夫です。
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-core -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-core</artifactId>
<version>2.9.9</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind -->
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.9.1</version>
</dependency>
<!-- https://mvnrepository.com/artifact/com.fasterxml.jackson.dataformat/jackson-dataformat-yaml -->
<dependency>
<groupId>com.fasterxml.jackson.dataformat</groupId>
<artifactId>jackson-dataformat-yaml</artifactId>
<version>2.9.9</version>
</dependency>
Yamlのパース時に使用する要素が定義されたクラスは変数の定義行に
@JsonPropertyアノテーションを付けてその中に要素の名前を入力すればOKです。
public class MusicSourceSection {
@JsonProperty("youtube")
private boolean youtube;
@JsonProperty("soundcloud")
private boolean soundcloud;
@JsonProperty("bandcamp")
private boolean bandcamp;
@JsonProperty("vimeo")
private boolean vimeo;
@JsonProperty("twitch")
private boolean twitch;
@JsonProperty("http")
private boolean http;
@JsonProperty("local")
private boolean local;
public boolean enableYoutube() {
return youtube;
}
public boolean enableSoundCloud() {
return soundcloud;
}
public boolean enableBandCamp() {
return bandcamp;
}
public boolean enableVimeo() {
return vimeo;
}
public boolean enableTwitch() {
return twitch;
}
public boolean enableHttp() {
return http;
}
public boolean enableLocal() {
return local;
}
}
上のコードにはありませんが、クラスが入れ子になっていても問題なく読み込めます。
ここまでできてしまえばあとはJsonのときと同じようにObjectMapperでroadValueをすれば指定したクラスの型で返ってきます。
ObjectMapper mapper = new ObjectMapper(new YAMLFactory());
mapper.readValue(new FileInputStream(file), MusicSourceSection.class);
Jacksonを使うことでこれまで使わないSetterで嵩張っていたクラスファイルがスッキリしました。
コメント