PredicateQueryParser { public void parseJsonQuery( String json, FeatureHandler<String> featureHandler, FeatureHandler<Long> rangeFeatureHandler) throws IllegalArgumentException { try (JsonParser parser = factory.createParser(json)) { skipToken(parser, JsonToken.START_OBJECT); while (parser.nextToken() != JsonToken.END_OBJECT) { String fieldName = parser.getCurrentName(); switch (fieldName) { case "features": parseFeatures(parser, JsonParser::getText, featureHandler); break; case "rangeFeatures": parseFeatures(parser, JsonParser::getLongValue, rangeFeatureHandler); break; default: throw new IllegalArgumentException("Invalid field name: " + fieldName); } } } catch (IllegalArgumentException e) { throw e; } catch (IOException e) { throw new AssertionError("This should never happen when parsing from a String", e); } catch (Exception e) { throw new IllegalArgumentException(String.format("Parsing query from JSON failed: '%s'", json), e); } }  void parseJsonQuery(
            String json, FeatureHandler<String> featureHandler, FeatureHandler<Long> rangeFeatureHandler);  }
@Test public void require_that_json_is_correctly_parsed() { String json = "{" + " \"features\":[" + " {\"k\":\"k1\",\"v\":\"value1\",\"s\":\"0x1\"}," + " {\"k\":\"k2\",\"v\":\"value2\",\"s\":\"0x3\"}" + " ],\"rangeFeatures\":[" + " {\"k\":\"range1\",\"v\":123456789123,\"s\":\"0xffff\"}," + " {\"k\":\"range2\",\"v\":0,\"s\":\"0xffffffffffffffff\"}" + " ]" + "}"; PredicateQueryParser parser = new PredicateQueryParser(); List<String> result = new ArrayList<>(); parser.parseJsonQuery( json, (k, v, s) -> result.add(String.format("%s:%s:%#x", k, v, s)), (k, v, s) -> result.add(String.format("%s:%d:%#x", k, v, s))); assertEquals(result, Arrays.asList( "k1:value1:0x1", "k2:value2:0x3", "range1:123456789123:0xffff", "range2:0:0xffffffffffffffff")); }