Spring や SpringBoot を使わない環境で、YAML からパスを指定した値の抽出です。
非Spring、非SpringBoot 環境で、YAMLを読む - Oboe吹きプログラマの黙示録
の応用です。
snakeyaml を使用します。
・パスは "." 区切りで並べます。
・配列の一部を抽出する場合は、インデックス [n] を後方に付けます
・受け取る型は、Object で、String か、List<String> を受け取ります。Map としては抽出しません。
・org.yaml.snakeyaml.Yaml と、YAML読込みの InputStream を指定します。
・(注意)1回の実行で InputStream 終端まで読み込みます。
という仕様で以下のメソッドを書いてみました。
pom.xml
<dependency> <groupId>org.yaml</groupId> <artifactId>snakeyaml</artifactId> <version>1.27</version> </dependency>
インポートするもの
import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.util.ArrayList; import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.regex.Pattern; import java.util.stream.Collectors; import org.yaml.snakeyaml.Yaml; import org.yaml.snakeyaml.events.Event; import org.yaml.snakeyaml.events.ScalarEvent;
static メソッド
/** * パスによる YAML抽出 * @param yaml org.yaml.snakeyaml.Yaml インスタンス * @param inst yaml読込みInputStream * @param path "." で区切ったパス、配列は、[n] を付与 * @return String または、List<String> を結果として返す */ public static Object parseYaml(Yaml yaml, InputStream inst, String path) { if (path.isEmpty()) throw new IllegalArgumentException("path Error"); List<String> plist = Arrays.stream(path.split("\\.")).collect(Collectors.toList()); String s = plist.remove(plist.size()-1); if (Pattern.compile("^.+\\[[0-9]+\\]$").matcher(s).matches()) { plist.add(s.substring(0, s.indexOf("["))); plist.add(s.substring(s.indexOf("["))); }else{ plist.add(s); } String result = null; boolean sequence = false; int length = plist.size(); boolean isSeq = false; int xseq = 0; List<String> list = new ArrayList<>(); if (Pattern.compile("^\\[[0-9]+\\]$").matcher(plist.get(plist.size()-1)).matches()) { isSeq = true; length--; String last = plist.get(plist.size()-1); xseq = Integer.parseInt(last.substring(1, last.length()-1)); } int n=0; int x=0; for(Iterator<Event> it = yaml.parse(new InputStreamReader(inst)).iterator();it.hasNext();) { Event e = it.next(); if (e.getEventId().equals(Event.ID.MappingStart)){ continue; }else if(e.getEventId().equals(Event.ID.SequenceStart)){ sequence = true; x=0; continue; }else if(e.getEventId().equals(Event.ID.SequenceEnd)){ if (list.size() > 0) { return list; } sequence = false; continue; } if (e.getEventId().equals(Event.ID.Scalar)){ if (n < length) { if (plist.get(n).equals(((ScalarEvent)e).getValue())) { n++; } }else{ if (sequence){ if (isSeq) { if (x==xseq){ result = ((ScalarEvent)e).getValue(); break; } }else{ list.add(((ScalarEvent)e).getValue()); continue; } x++; }else{ if (n==plist.size()) { result = ((ScalarEvent)e).getValue(); break; } } } } } return result; }
使用例
try(InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("sample.yml")){ Yaml yaml = new Yaml(); String info1 = (String)parseYaml(yaml, in, "address.group.info1"); }catch(IOException e){ e.printStackTrace(); }
try(InputStream in = ClassLoader.getSystemClassLoader().getResourceAsStream("sample.yml")){ Yaml yaml = new Yaml(); String info1 = (String)parseYaml(yaml, in, "address.group.clist[2]"); }catch(IOException e){ e.printStackTrace(); }