【问题标题】:How can I populate fields of a JSON schema in Java如何在 Java 中填充 JSON 模式的字段
【发布时间】:2019-01-20 15:37:37
【问题描述】:

我正在尝试填充 JSON 对象,以便将其发送到 REST 端点并获得响应。

没有“构建”这些请求的 API,所以我只是存储一个如下所示的 JSON 文本文件:

"query": {
  "bool": {
    "must": [
      {
        "range": {
          "request_time": {
            "gte": {{START_TIME}},
            "lte": {{END_TIME}},
            "format": "epoch_millis"
          }
        }
      }
    ],
    "filter": [
      {
        "match_all": {}
      },
      {
        "geo_bounding_box": {
          "{{LOCATION_FIELD_NAME}}": {
            "top_left": {
              "lat": {{TOP_LEFT_LAT}},
              "lon": {{TOP_LEFT_LON}}
            },
            "bottom_right": {
              "lat": {{BOTTOM_RIGHT_LAT}},
              "lon": {{BOTTOM_RIGHT_LON}}
            }
          }
        }
      }
    ],
    "should": [],
    "must_not": []
  }
}

然后我用键、值对填充一个 HashMap,其中键是 {{*EXPRESSION*}},值是我希望替换它们的 StringsDoubles 等。

最后,我通过文本文件搜索分隔符:{{}},并将键替换为值。

这对我来说似乎真的是贫民窟,而且显然很难测试。我正在使用 Jackson 库来解析我的响应,ObjectMapper 可以让您将 JSON 转换为 POJO 并返回,这很好,但我不想经历定义 15 个类的麻烦,只是为了编译上面的骨架(我知道每次都是一样的)。是否有一种通过文本文件向 Jackson 提供 JSON 模式并仅填充某些字段的事实上的方法?

谢谢!

【问题讨论】:

  • 手动编写 json 对于小事情可能很好,但它可能会变得很麻烦,如果你开始有需要转义的字符、日期等,更是如此。我找到的最简单的方法是这样做正在使用谷歌的 gson 库。
  • 如何使用 java String API 替换 json 字符串中的表达式,然后从更新的字符串中形成一个对象(单个对象)?
  • 一种方法是将模板解析为带有mapper.readTreeJsonNode,然后遍历树以更新您的模板值。它会更健壮,因为您可以确定您的序列化值是有效的 JSON。

标签: java json jackson schema populate


【解决方案1】:

Jackson 确实有一个用于操作 JSON 树的 API。您可以使用它从文件或字符串中读取模板,然后只更新您需要的部分。

使用readTree 解析您的模板:

ObjectMapper mapper = new ObjectMapper();

ObjectNode template = (ObjectNode) mapper.readTree(
    "{\n" +
    "  \"query\": {\n" +
    "    \"bool\": {\n" +
    "      \"must\": [],\n" +
    "      \"filter\": [{\"match_all\": {}}],\n" +
    "      \"should\": [],\n" +
    "      \"must_not\": []\n" +
    "    }\n" +
    "  }\n" +
    "}");

然后使用 JSON 指针找到要更新的节点:

ArrayNode must = (ArrayNode) template.at("/query/bool/must");

并更新它:

must
    .addObject()
    .with("range")
    .with("request_time")
    .put("gte", "2018-01-14T00:00:00.000Z")
    .put("lte", "2018-01-13T00:00:00.000Z")
    .put("format", "epoch_millis");

您甚至可以将它与对象映射 API 混合使用:

ArrayNode filter = (ArrayNode) template.at("/query/bool/filter");
filter.addObject()
    .with("geo_bounding_box")
    .putPOJO(
        "custom_location",
        new GeoBoundingBox(
            new LatLon(-36.854307, 174.771923),
            new LatLon(-36.861172, 174.780636)
        )
    );

树的序列化与对象的执行方式相同:

mapper
    .writerWithDefaultPrettyPrinter()
    .withoutFeatures(JsonGenerator.Feature.AUTO_CLOSE_TARGET)
    .writeValue(System.out, template);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-05-20
    • 1970-01-01
    • 2014-07-24
    • 2016-04-25
    • 2016-05-11
    • 2017-10-24
    • 2018-10-15
    • 2016-02-01
    相关资源
    最近更新 更多