【问题标题】:How to deep select Nodes based on given depth in Java?如何根据 Java 中的给定深度深度选择节点?
【发布时间】:2020-04-14 08:54:08
【问题描述】:

我有如下的 json 表示:

{
  "total": "555",
  "offset": "555",
  "hasMore": "false",
  "results": [
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "child": {
         "name" : "association1",
          "key" : "a1"
        }, 
        "quoteIds": [],
        "contentIds": [],
        "dealIds": [],
        "contactIds": [
          4646915
        ],
        "ticketIds": []
      },
      "scheduledTasks": [
        {
          "taskType": "REMINDER",
          "portalId": 214129,
          "engagementType": "TASK",
          "engagementId": 6604524566,     
          "timestamp": 1586815200000
        }
      ]
    },
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "quoteIds": [],
        "contentIds": [],
        "child": {
         "name" : "association2",
          "key" : "a2"
        }, 
        "dealIds": [],
        "contactIds": [
          4646915
        ],
        "ticketIds": []
      }
    },
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "quoteIds": [],
        "contentIds": [],
        "dealIds": [],
        "child": {
         "name" : "association3",
          "key" : "a3"
        }, 
        "contactIds": [
          3995065
        ],
        "ticketIds": []
      }
    },
    {
      "associations": {
        "workflowIds": [],
        "companyIds": [],
        "ownerIds": [],
        "quoteIds": [],
        "contentIds": [],
        "dealIds": [],
        "contactIds": [
          4648365
        ],
        "ticketIds": []
      }
    }
]
}

我想通过传递节点选择器字符串来获取给定节点的 过滤信息(类似于 sql),为此我正在执行以下操作:

ObjectMapper objectMapper = new ObjectMapper();
        JsonNode root = objectMapper.readTree(new File("/Users/pra/automation/foo.json"));
       String result = root.at("/results/0/associations/0/child").toString();
       Assert.assertNotNull(result);

并且这段代码也可以正常工作,它会从数组中过滤出第一个节点,因为传递了 0 级索引,但是我需要输出所有匹配元素,以实现我传递 * 而不是 0 但它不工作.

意味着我正在尝试类似下面的东西(失败):

String result = root.at("/results/*/associations/*/child").toString();

所需的输出:

[
{
   "name" : "association1",
   "key" : "a1"
},
{
   "name" : "association2",
   "key" : "a2"
},
{
   "name" : "association3",
   "key" : "a3"
}
]

我愿意接受其他基于 Java 的替代方案来实现这一目标。谢谢。

【问题讨论】:

  • 使用该直接访问权限吗?难道你不能简单地迭代不同的结果和孩子并将它们一起累积在一个数组中
  • @Lino - 是的,我不想迭代,因为我正在寻找动态并且我的节点长度 ID 会发生变化
  • 寻找直接访问。
  • 您要查找的是 JSONPath,它对 JSON 的作用与 XPath 对 XML 的作用相同。 --- 有关 Java 库,请参阅 Jayway JsonPath
  • @PramodS.Nikam 我已经发布了那个链接:Jayway JsonPathhttps://github.com/json-path/JsonPath#jayway-jsonpath

标签: java json spring jackson modelmapper


【解决方案1】:

如果您可以切换到 Gson 库,您可以使用 im.wilk.vor:VoritemgitHub 或在 Maven 存储库中。

VorItem vorItemFactory = VorItemFactoryBuilder.standard.build();
JsonElement je = JsonParser.parse(...)

VorItem vi = vorItemFactory.from(je);
VorItem result = vorItemFactory.empty();

for (int idx = 0; idx < vi.get("result").list().size(); idx++) {
    result.get(idx).set("name", vi.get("result").get(idx).get("associations/child/name");
    result.get(idx).set("key", vi.get("result").get(idx).get("associations/child/key");

}

return result.asJsonElement().toString();

【讨论】:

  • - 非常感谢您的建议!
【解决方案2】:

我发现 Andreas 的建议非常有效且易于使用,我能够通过使用 JSONPath library 来实现所需的输出。

使用代码如下:

ObjectMapper objectMapper = new ObjectMapper();
String root = objectMapper.readTree(new File("/Users/pramo/automation/foo.json")).toString();
List<Object> associations = JsonPath.read(root, "$.results[*].associations.child");

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-27
    • 2013-06-23
    • 1970-01-01
    • 1970-01-01
    • 2020-07-19
    • 1970-01-01
    相关资源
    最近更新 更多