(nb this solution is tested only with Jackson 2)
This can be done by wrapping JsonParser and simply applying .toLowerCase()
to all field names:
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(); } }
Then you must have a custom JsonFactory to apply your wrapper, as in this test:
@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" ) ))); }