JSONのキーから、JsonElement - Oboe吹きプログラマの黙示録
"." ドットで繋げたJSONのキーから JsonElement を抽出する
これを更に、関数型インターフェースにする。Reader 、JsonElement 、JSON文字列、各々に対するパターンを
書いたが、JsonElement に対するこのインスタンスは、PATH を変えながら再利用できるはずだ。
package org.yipuran.gsonhelper; import java.io.Reader; import java.io.Serializable; import java.io.StringReader; import java.util.Optional; import java.util.Spliterator; import java.util.Spliterators; import java.util.function.Consumer; import java.util.stream.StreamSupport; import com.google.gson.JsonElement; import com.google.gson.JsonParser; /** * JSONキーPATHによるJsonElement抽出. */ @FunctionalInterface public interface JsonPathSearch extends Serializable{ void accept(Optional<JsonElement> je); public static JsonPathSearch of(Consumer<Optional<JsonElement>> consumer){ return e->consumer.accept(e); } default void compute(String key, JsonElement je){ accept(elementParse(je, key)); } default void compute(String key, Reader reader){ accept(elementParse(new JsonParser().parse(reader), key)); } default void compute(String key, String jsonstring){ accept(elementParse(new JsonParser().parse(new StringReader(jsonstring==null ? "" : jsonstring)), key)); } static Optional<JsonElement> elementParse(JsonElement je, String key){ if (!je.isJsonObject()) return Optional.empty(); if (key.contains(".")){ String[] sp = key.split("\\."); if (sp.length > 1){ return StreamSupport.stream(Spliterators.spliteratorUnknownSize( je.getAsJsonObject().entrySet().iterator(), Spliterator.ORDERED ), false) .filter(e->e.getKey().equals(sp[0])).findAny() .flatMap(e->elementParse(e.getValue(), key.replaceFirst("^[\\w_]+\\.", ""))); }else{ return StreamSupport.stream(Spliterators.spliteratorUnknownSize( je.getAsJsonObject().entrySet().iterator(), Spliterator.ORDERED ), false) .filter(e->e.getKey().equals(sp[0])).findAny().map(e->e.getValue()); } } return StreamSupport.stream(Spliterators.spliteratorUnknownSize( je.getAsJsonObject().entrySet().iterator(), Spliterator.ORDERED ), false) .filter(e->e.getKey().equals(key)).findAny().map(e->e.getValue()); } }
使用例、JSON ファイルの内容が以下の場合、
{ "a":{ "b":{ "c": 2345 , "num":[0,1,2] } } }
try(InputStream in = new FileInputStream("test.json"); Reader reader = new InputStreamReader(in, "UTF-8")){ JsonElement je = new JsonParser().parse(reader); JsonPathSearch js = JsonPathSearch.of(je->{ je->je.ifPresent(e->{ System.out.println( e.getAsInt() ); }); }); js.compute("a.b.c", je); }catch(IOException e){ e.printStackTrace(); }
あるいは、"a.b.num" を指定して、取得する配列を JsonArray に変換して処理する。
JsonPathSearch.of(je->{ je.ifPresent(e->{ e.getAsJsonArray().forEach(t->{ System.out.println( t.getAsInt() ); }); }); }).compute("a.b.num", reader);