我正在使用 Jackson (1.9.x) 库将 JSON 解析为 Map:
ObjectMapper mapper = new ObjectMapper();
Map<String,Object> map = (Map<String,Object>) mapper.readValue(jsonStr, Map.class);
Run Code Online (Sandbox Code Playgroud)
有没有办法告诉 Jackson 解析器将所有键的名称小写?我尝试使用 Jackson PropertyNamingStrategy,但这没有用 - 它似乎只有在映射到某个 bean 而不是 Map 时才有用。
说明:
传入的 JSON:
{"CustName":"Jimmy Smith","Result":"foo","CustNo":"1234"}
Run Code Online (Sandbox Code Playgroud)
Java 地图将具有:
"custname" => "Jimmy Smith"
"result" => "foo"
"custno" => "1234"
Run Code Online (Sandbox Code Playgroud)
[更新]:我在下面给出的答案并没有完全解决问题。仍在寻找解决方案。
(注意此解决方案仅与 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();
}
}
Run Code Online (Sandbox Code Playgroud)
然后你必须有一个自定义的 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"
)
)));
}
Run Code Online (Sandbox Code Playgroud)
我想出了一种方法来做到这一点。使用 a org.codehaus.jackson.map.KeyDeserializer,将其放入 a 中SimpleModule并向 Jackson 注册该模块ObjectMapper。
import org.codehaus.jackson.map.KeyDeserializer;
import org.codehaus.jackson.map.ObjectMapper;
import org.codehaus.jackson.map.module.SimpleModule;
import org.codehaus.jackson.Version;
// ...
class LowerCaseKeyDeserializer extends KeyDeserializer {
@Override
public Object deserializeKey(String key, DeserializationContext ctx)
throws IOException, JsonProcessingException {
return key.toLowerCase();
}
}
// ...
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule("LowerCaseKeyDeserializer",
new Version(1,0,0,null));
module.addKeyDeserializer(Object.class, new LowerCaseKeyDeserializer());
mapper.registerModule(module);
Map<String,Object> map =
(Map<String,Object>) mapper.readValue(jsonStr, Map.class);
Run Code Online (Sandbox Code Playgroud)
[更新]:实际上这只会小写顶级映射键,但不会小写嵌套键。
如果输入是:
{"CustName":"Jimmy Smith","CustNo":"1234","Details":{"PhoneNumber": "555-5555", "Result": "foo"}}
Run Code Online (Sandbox Code Playgroud)
不幸的是,地图中的输出将是:
{"custname"="Jimmy Smith", "custno"="1234", "details"={"PhoneNumber"="555-5555", "Result"="foo"}}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
7977 次 |
| 最近记录: |