JSON を Jackson の ObjectMapper でクラスにマッピングするのではなく、
JSON キー と 値の BiConsumer を実行する。
ObjectMapper の readTree メソッドで取得する JsonNode を使用する。
import java.io.IOException; import java.io.InputStream; import java.util.AbstractMap.SimpleEntry; import java.util.Iterator; import java.util.Map.Entry; import java.util.function.BiConsumer; import java.util.function.Predicate; import java.util.stream.Stream; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.node.JsonNodeType; /** * JsonNodeParse */ public class JsonNodeParse{ public void readJson(String jsontxt, BiConsumer<String, Object> con){ ObjectMapper mapper = new ObjectMapper(); try{ parseJson(mapper.readTree(jsontxt), "", con); }catch (JsonProcessingException e){ throw new RuntimeException(e); } } public void readJson(InputStream in, BiConsumer<String, Object> con){ ObjectMapper mapper = new ObjectMapper(); try{ parseJson(mapper.readTree(in), "", con); }catch (JsonProcessingException e){ throw new RuntimeException(e); }catch(IOException e){ throw new RuntimeException(e); } } private void parseJson(JsonNode node, String path, BiConsumer<String, Object> con){ if (node.getNodeType().equals(JsonNodeType.OBJECT)) { for(Iterator<Entry<String, JsonNode>> it=node.fields(); it.hasNext();) { Entry<String, JsonNode> entry = it.next(); parseJson(entry.getValue(), path + "." + entry.getKey(), con); } }else if(node.getNodeType().equals(JsonNodeType.ARRAY)){ if (node.size() > 0){ int x=0; for(Iterator<JsonNode> it=node.iterator(); it.hasNext();x++){ parseJson(it.next(), path + "[" + x + "]", con); } }else{ con.accept(path.substring(1), new ArrayList<Object>()); } }else if(node.getNodeType().equals(JsonNodeType.NULL)){ con.accept(path.substring(1), null); }else if(node.getNodeType().equals(JsonNodeType.NUMBER)){ if (node.isDouble()){ con.accept(path.substring(1), node.asDouble()); }else if(node.isLong()){ con.accept(path.substring(1), node.asLong()); }else{ con.accept(path.substring(1), node.asInt()); } }else if(node.getNodeType().equals(JsonNodeType.BOOLEAN)){ con.accept(path.substring(1), node.asBoolean()); }else if(node.getNodeType().equals(JsonNodeType.STRING)){ con.accept(path.substring(1), node.asText()); } } public void readJson(String jsontxt, Predicate<String> pathfilter, BiConsumer<String, Object> con){ ObjectMapper mapper = new ObjectMapper(); try{ parseJson(mapper.readTree(jsontxt), "", pathfilter, con); }catch (JsonProcessingException e){ throw new RuntimeException(e); } } public void readJson(InputStream in, Predicate<String> pathfilter, BiConsumer<String, Object> con){ ObjectMapper mapper = new ObjectMapper(); try{ parseJson(mapper.readTree(in), "", pathfilter, con); }catch (JsonProcessingException e){ throw new RuntimeException(e); }catch(IOException e){ throw new RuntimeException(e); } } private void parseJson(JsonNode node, String path, Predicate<String> pathfilter, BiConsumer<String, Object> con){ if (node.getNodeType().equals(JsonNodeType.OBJECT)) { for(Iterator<Entry<String, JsonNode>> it=node.fields(); it.hasNext();) { Entry<String, JsonNode> entry = it.next(); parseJson(entry.getValue(), path + "." + entry.getKey(), pathfilter, con); } }else if(node.getNodeType().equals(JsonNodeType.ARRAY)){ if (node.size() > 0){ int x=0; for(Iterator<JsonNode> it=node.iterator(); it.hasNext();x++){ parseJson(it.next(), path + "[" + x + "]", pathfilter, con); } }else{ con.accept(path.substring(1), new ArrayList<Object>()); } }else if(node.getNodeType().equals(JsonNodeType.NULL)){ String p = path.substring(1); if (pathfilter.test(p)){ con.accept(p, null); } }else if(node.getNodeType().equals(JsonNodeType.NUMBER)){ String p = path.substring(1); if (pathfilter.test(p)){ if (node.isDouble()){ con.accept(p, node.asDouble()); }else if(node.isLong()){ con.accept(p, node.asLong()); }else{ con.accept(p, node.asInt()); } } }else if(node.getNodeType().equals(JsonNodeType.BOOLEAN)){ String p = path.substring(1); if (pathfilter.test(p)){ con.accept(p, node.asBoolean()); } }else if(node.getNodeType().equals(JsonNodeType.STRING)){ String p = path.substring(1); if (pathfilter.test(p)){ con.accept(p, node.asText()); } } } }
JSON キーは、"." 区切りで連結し、配列は、"[n]" で表現する
使用例
JsonNodeParse jsonNodeparse = new JsonNodeParse(); jsonNodeparse.readJson(jsontxt, (p, o)->{ System.out.println("path = " + p + " value = "+ o); });
{ "id" : 1207, "name" : "テストFoo", "cat" : [ 22, 33 ], "mod" : null, "flg" : true, "group" : { "hub": "Test", "length": 120.45 } }
結果
path = id value = 1207 path = name value = テストFoo path = cat[0] value = 22 path = cat[1] value = 33 path = mod value = null path = flg value = true path = group.hub value = Test path = group.length value = 120.45
また、おまけのようではあるが、
Json キー、パスの Predicate で
JsonNodeParse jsonNodeparse = new JsonNodeParse(); jsonNodeparse.readJson(jsontxt, p->p.startsWith("group.") , (p, o)->{ System.out.println("path = " + p + " value = "+ o); });
path = group.hub value = Test path = group.length value = 120.45