使用嵌套映射中的同级键值对访问子节点

时间:2016-09-23 13:57:51

标签: java json

我有一个嵌套的复杂结构,如下所示。我试图用它的兄弟键:值对来访问嵌套键的值。

例如:我的复杂结构是:

 {

    key1:value,

     key2:

         [

         {a:1,c:{d:1}},

         {a:2,c:{d:0}}, 

        {a:3,c:{d:1}}

         ]

     }

我试图返回d的值,其中a:3。很明显,d是兄弟姐妹的孩子。如果我遍历key2并得到c的值,我可以在c的子节点上做一个DFS来找到所需的值。

如果我指定一个兄弟键:值对作为一个嵌套级别,这将无济于事。它需要像遍历一样的XPath。对于上述情况,我的表达式是:

(a:1>>c)->{d:1}
(a:2>>c::d)->0
(key2::a)->[1,2,3]

where ::是儿童表示法,>>是一个兄弟符号。 是否有简单或优雅的方式来接近这个?是否有像this这样的库来解决这个问题?

1 个答案:

答案 0 :(得分:1)

您可以使用Java 8库Dynamics解决这些问题。它允许您以直接但流畅的方式遍历嵌套结构。无效的方式。

Map nestedStructure = ...
// {key1=value, key2=[{a=1, c={d=1}}, {a=2, c={d=0}}, {a=3, c={d=1}}]}
Dynamic data = Dynamic.from(nestedStructure);

// "(a:1>>c)": all "c" values that have sibling "a" = 1
List<Map> aIs1CValues = data.allChildren()
    // filter to elements that have an 'a=3' child & a "c" map child
    .filter(el -> el.get("a").maybe().as(Integer.class).orElse(0) == 1)
    .filter(el -> el.get("c").isMap())
    .map(el -> el.get("c").asMap())
    .collect(toList()); // [{d=1}]

// "(a:2>>c::d)": all "d" values, with parent key "c" that has sibling "a" = 2
List<Integer> aIs2DValues = data.allChildren()
    .filter(el -> el.get("a").maybe().as(Integer.class).orElse(0) == 2)
    .filter(el -> el.dget("c.d").is(Integer.class))
    .map(el -> el.dget("c.d").as(Integer.class))
    .collect(toList()); // [0]

// "(key2::a)": all "a" values, with some parent key "key2"
List<Integer> key2As = data.allChildren()
    .filter(el -> el.key().asObject().equals("key2"))
    .flatMap(Dynamic::children)
    .filter(key2Map -> key2Map.get("a").is(Integer.class))
    .map(key2Map -> key2Map.get("a").as(Integer.class))
    .collect(toList()); // [1, 2, 3]

我不能完全确定您的真实问题与您的示例相比,如果我们对数据有更多了解,这种处理可能会更简单。例如,如果我们知道 key2 是最高级别且 a 始终存在且是整数,则最后一个问题会更容易。

data.get("key2").children()
    .map(child -> child.get("a").as(Integer.class))
    .collect(toList()); // [1, 2, 3]

有关来源,文档和示例,请参阅https://github.com/alexheretic/dynamics