java - 如何使用 Jackson 将 JSON 解析为带有小写键的 Map?

标签 java json jackson

我正在使用 Jackson (1.9.x) 库将 JSON 解析为 Map:

ObjectMapper mapper = new ObjectMapper();
Map<String,Object> map = (Map<String,Object>) mapper.readValue(jsonStr, Map.class);

有没有办法告诉 Jackson 解析器将所有键的名称小写?我尝试使用 Jackson PropertyNamingStrategy,但这没有用 - 它似乎只有在映射到某个 bean 而不是 Map 时才有用。

说明:

  1. 我不想为 JSON 预先创建 beans - 我只想要动态 map
  2. 传入的 JSON 键不会是小写的,但我希望所有的映射键都是小写的(请参见下面的示例)
  3. JSON 相当大且嵌套严重,因此根本不需要对传入的 JSON 进行正则表达式替换或在 Jackson 解析后手动创建新映射。

传入的 JSON:

{"CustName":"Jimmy Smith","Result":"foo","CustNo":"1234"}

Java 映射将具有:

"custname" => "Jimmy Smith"
"result" => "foo"
"custno" => "1234"

[更新]:我在下面给出的答案并没有完全解决问题。仍在寻找解决方案。

最佳答案

(注意此解决方案仅使用 Jackson 2 进行测试)

可以通过包装 JsonParser 并简单地将 .toLowerCase() 应用于所有字段名称来做到这一点:

private static final class DowncasingParser extends JsonParserDelegate {
    private DowncasingParser(JsonParser d) {
        super(d);
    }

    @Override
    public String getCurrentName() throws IOException, JsonParseException {
        if (hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
            return delegate.getCurrentName().toLowerCase();
        }
        return delegate.getCurrentName();
    }

    @Override
    public String getText() throws IOException, JsonParseException {
        if (hasTokenId(JsonTokenId.ID_FIELD_NAME)) {
            return delegate.getText().toLowerCase();
        }
        return delegate.getText();
    }
}

然后你必须有一个自定义的 JsonFactory 来应用你的包装器,就像在这个测试中一样:

@Test
public void downcase_map_keys_by_extending_stream_parser() throws Exception {
    @SuppressWarnings("serial")
    ObjectMapper mapper = new ObjectMapper(new JsonFactory() {
        @Override
        protected JsonParser _createParser(byte[] data, int offset, int len, IOContext ctxt) throws IOException {
            return new DowncasingParser(super._createParser(data, offset, len, ctxt));
        }

        @Override
        protected JsonParser _createParser(InputStream in, IOContext ctxt) throws IOException {
            return new DowncasingParser(super._createParser(in, ctxt));
        }

        @Override
        protected JsonParser _createParser(Reader r, IOContext ctxt) throws IOException {
            return new DowncasingParser(super._createParser(r, ctxt));
        }

        @Override
        protected JsonParser _createParser(char[] data, int offset, int len, IOContext ctxt, boolean recyclable)
                throws IOException {
            return new DowncasingParser(super._createParser(data, offset, len, ctxt, recyclable));
        }
    });
    assertThat(
            mapper.reader(Map.class)
                    .with(JsonParser.Feature.ALLOW_UNQUOTED_FIELD_NAMES)
                    .with(JsonParser.Feature.ALLOW_SINGLE_QUOTES)
                    .readValue("{CustName:'Jimmy Smith', CustNo:'1234', Details:{PhoneNumber:'555-5555',Result:'foo'} } }"),
            equalTo((Map<String, ?>) ImmutableMap.of(
                    "custname", "Jimmy Smith",
                    "custno", "1234",
                    "details", ImmutableMap.of(
                            "phonenumber", "555-5555",
                            "result", "foo"
                            )
                    )));
}

关于java - 如何使用 Jackson 将 JSON 解析为带有小写键的 Map?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/18838095/

相关文章:

java - 模拟 Vertx.io 异步处理程序

Python jsonschema 无法验证字符串枚举

javascript - Grails - 使用 JSON 通过 Ajax 从 Controller 渲染 map

java - Jackson Json Parser-如何处理未找到值的异常

java - 如何在 JAX-WS 客户端中禁用证书验证?

java - 重用部分 Drools `when` 语句

java - 这种情况下最好的数据结构和算法是什么?

json - 使用 Nodatime 反序列化 json 会产生空值

java - 如何在 Spring Boot 中自定义 JSON 响应?

java - 如何将多个 Map<String,String> 解包为 Json