@VisibleForTesting
    static LookupResult parseBody(JsonPath singleJsonPath, @Nullable JsonPath multiJsonPath, InputStream body) {
        try {
            final DocumentContext documentContext = JsonPath.parse(body);

            LookupResult.Builder builder = LookupResult.builder().cacheTTL(Long.MAX_VALUE);

            if (multiJsonPath != null) {
                try {
                    final Object multiValue = documentContext.read(multiJsonPath);

                    if (multiValue instanceof Map) {
                        //noinspection unchecked
                        builder = builder.multiValue((Map<Object, Object>) multiValue);
                    } else if (multiValue instanceof List) {
                        //noinspection unchecked
                        final List<String> stringList = ((List<Object>) multiValue).stream().map(Object::toString).collect(Collectors.toList());
                        builder = builder.stringListValue(stringList);

                        // for backwards compatibility
                        builder = builder.multiSingleton(multiValue);
                    } else {
                        builder = builder.multiSingleton(multiValue);
                    }
                } catch (PathNotFoundException e) {
                    LOG.warn("Couldn't read multi JSONPath from response - skipping multi value ({})", e.getMessage());
                }
            }

            try {
                final Object singleValue = documentContext.read(singleJsonPath);

                if (singleValue instanceof CharSequence) {
                    return builder.single((CharSequence) singleValue).build();
                } else if (singleValue instanceof Number) {
                    return builder.single((Number) singleValue).build();
                } else if (singleValue instanceof Boolean) {
                    return builder.single((Boolean) singleValue).build();
                } else {
                    throw new IllegalArgumentException("Single value data type cannot be: " + singleValue.getClass().getCanonicalName());
                }
            } catch (PathNotFoundException e) {
                LOG.warn("Couldn't read single JSONPath from response - returning empty result ({})", e.getMessage());
                return null;
            }
        } catch (InvalidJsonException e) {
            LOG.error("Couldn't parse JSON response", e);
            return null;
        } catch (ClassCastException e) {
            LOG.error("Couldn't assign value type", e);
            return null;
        } catch (Exception e) {
            LOG.error("Unexpected error parsing JSON response", e);
            return null;
        }
    }
@Test
    public void parseBodyWithMapMultiValue() throws Exception {
        final JsonPath singlePath = JsonPath.compile("$.hello");
        final JsonPath multiPath = JsonPath.compile("$.map");
        final LookupResult result = HTTPJSONPathDataAdapter.parseBody(singlePath, multiPath, body);

        assertThat(result.isEmpty()).isFalse();
        assertThat(result.hasError()).isFalse();
        assertThat(result.singleValue()).isEqualTo("world");

        assertThat(result.multiValue()).isNotNull();
        assertThat(result.multiValue()).isInstanceOf(Map.class);
        assertThat(result.multiValue()).containsOnly(
                entry("key1", "value1"),
                entry("key2", "value2")
        );
    }