標準ライブラリにある javax.script.ScriptEngine で、
JavaScript として解釈させて Nashorn で参照する方法です。
Google gson みたいな高機能は期待できません。
Nashorn は、Java11 から非奨励です。
Java15 から廃止されてます
書いては、みたものの、非奨励だから使わない方法です。
import java.util.HashMap; import java.util.Map; import java.util.Optional; import javax.script.ScriptEngine; import javax.script.ScriptEngineManager; import javax.script.ScriptException; import jdk.nashorn.api.scripting.ScriptObjectMirror; import com.google.common.collect.Lists; import com.google.common.collect.Maps; /** * JsonBody */ public class JsonBody{ private ScriptEngine engine; public JsonBody(String json) throws ScriptException{ ScriptEngineManager manager = new ScriptEngineManager(); engine = manager.getEngineByName("JavaScript"); String script = "var _obj=" + json + ";"; engine.eval(script); } public static JsonBody of(String json) throws ScriptException{ return new JsonBody(json); } public Object getObject(String path) { try{ return engine.eval("_obj." + path); }catch(ScriptException e){ e.printStackTrace(); } return null; } public String getString(String path) { try{ return Optional.ofNullable(engine.eval("_obj." + path)) .map(e->e.toString()).orElse(null); }catch(ScriptException e){ e.printStackTrace(); } return null; } public Integer getInt(String path) { try{ return Optional.ofNullable(engine.eval("_obj." + path)) .map(e->Integer.valueOf(e.toString())).orElse(null); }catch(ScriptException e){ e.printStackTrace(); } return null; } public Double getDouble(String path) { try{ return Optional.ofNullable(engine.eval("_obj." + path)) .map(e->Double.valueOf(e.toString())).orElse(null); }catch(ScriptException e){ e.printStackTrace(); } return null; } public Object[] getObjectArray(String path) { try{ ScriptObjectMirror mirror = (ScriptObjectMirror)engine.eval("_obj." + path); if (mirror.isArray()){ return mirror.to(Object[].class); }else{ return new Object[]{}; } }catch(ScriptException e){ e.printStackTrace(); } return new Object[]{}; } public Integer[] getIntArray(String path) { try{ ScriptObjectMirror mirror = (ScriptObjectMirror)engine.eval("_obj." + path); if (mirror.isArray()){ return mirror.to(Integer[].class); }else{ return new Integer[]{}; } }catch(ScriptException e){ e.printStackTrace(); } return new Integer[]{}; } public Double[] getDoubleArray(String path) { try{ ScriptObjectMirror mirror = (ScriptObjectMirror)engine.eval("_obj." + path); if (mirror.isArray()){ return mirror.to(Double[].class); }else{ return new Double[]{}; } }catch(ScriptException e){ e.printStackTrace(); } return new Double[]{}; } @SuppressWarnings("unchecked") public Map<String, Object> getMap(String path) { try{ return (Map<String, Object>)convertIntoJavaObject(engine.eval("_obj." + path)); }catch(ScriptException e){ e.printStackTrace(); } return new HashMap<>(); } private Object convertIntoJavaObject(Object scriptObj) { if (scriptObj instanceof ScriptObjectMirror) { ScriptObjectMirror scriptObjectMirror = (ScriptObjectMirror) scriptObj; if (scriptObjectMirror.isArray()) { List<Object> list = Lists.newArrayList(); for (Map.Entry<String, Object> entry : scriptObjectMirror.entrySet()){ list.add(convertIntoJavaObject(entry.getValue())); } return list; }else { Map<String, Object> map = Maps.newHashMap(); for(Map.Entry<String, Object> entry : scriptObjectMirror.entrySet()){ map.put(entry.getKey(), convertIntoJavaObject(entry.getValue())); } return map; } }else{ return scriptObj; } } }
読込みパスの指定:
JavaScript の世界の Path の指定と同じ、"." ドット(ピリオド)で区切って指定します。
例)
{ "a" : "A00", "b" : 11, "c" : { "d" : [ 1, 2, 3 ], "e" : "E" } }
呼び出し例
JsonBody body = new JsonBody(json); String e = body.getString("c.e"); Integer[] ary = body.getIntArray("c.d");
(注意)
配列の読込や Map としての読込の為に、
jdk.nashorn.api.scripting.ScriptObjectMirror
を使ってます。
これは、通常のビルドでは、
Eclipse デフォルト設定のままでは、アクセス制限の警告が出ます。。
The type 'ScriptObjectMirror' is not API
(restriction on required library 'C:\Java\jdk1.8.0_231\jre1.8.0_231\lib\ext\nashorn.jar')
警告なので、動くことは動きますが、ビルドパス指定した方が良さそうです。