json-path / JsonPath

Java JsonPath implementation
Apache License 2.0
8.85k stars 1.63k forks source link

[version: 2.7.0] Json-smart provider does not support TypeRef! Use a Jackson or Gson based providerJson-smart provider does not support TypeRef! Use a Jackson or Gson based provider #802

Open shenngw1127 opened 2 years ago

shenngw1127 commented 2 years ago

static method

    public static <T> List<T> getJsonPathList2(String jsonString,
                                               String jsonPath,
                                               Class<T> tClass) {
        final ObjectMapper objectMapper2 = new ObjectMapper()
                .setPropertyNamingStrategy(PropertyNamingStrategy.UPPER_CAMEL_CASE)
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        final Configuration conf2 =
                Configuration.builder()
                        .jsonProvider(new JacksonJsonProvider(objectMapper2))
                        .options(Option.SUPPRESS_EXCEPTIONS)
                        .build();
        return JsonPath.using(conf2).parse(jsonString)
                .read(jsonPath, new TypeRef<List<T>>() {
                    @Override
                    public Type getType() {
                        return objectMapper2.getTypeFactory().constructParametricType(List.class,
                                tClass);
                    }
                });
    }

call static method

    @Test
    void test() {
        List<DataModel> dataModelList = JsonPathUtils.getJsonPathList2("{\"Items\": []}",
                "Items", DataModel.class);
        log.debug("dataModelList: {}", dataModelList);
        assertEquals(0, dataModelList.size());
    }

error here

java.lang.UnsupportedOperationException: Json-smart provider does not support TypeRef! Use a Jackson or Gson based provider

    at com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider.map(JsonSmartMappingProvider.java:94)
    at com.jayway.jsonpath.internal.JsonContext.convert(JsonContext.java:121)

version: 2.6.0 or 2.7.0

SingingBush commented 2 years ago

I was having this same problem and thought it was a bug. Turns out I had probably seen some broken example code.

At first I just configured the JacksonJsonProvider like so:

final TypeRef<List<MyPojo>> typeReference = new TypeRef<>() {};

final List<MyPojo> argusMessages = JsonPath.using(
        Configuration.builder()
                .jsonProvider(new JacksonJsonProvider(new ObjectMapper()))
                .build()
    )
    .parse(responseJson)
    .read("$['aggregations']['my_agg']['buckets'][*]['latest']['hits']['hits'][0]['_source']", typeReference);

but it failed with the message:

java.lang.UnsupportedOperationException: Json-smart provider does not support TypeRef! Use a Jackson or Gson based provider

    at json.path@2.7.0/com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider.map(JsonSmartMappingProvider.java:94)
    at json.path@2.7.0/com.jayway.jsonpath.internal.JsonContext.convert(JsonContext.java:121)
    at json.path@2.7.0/com.jayway.jsonpath.internal.JsonContext.read(JsonContext.java:103)

When debugging I can see that the configuration in JsonContext has a Jackson provider but a JsonSmart mapping provider: image

So I changed my code to also set the JacksonMappingProvider:

final TypeRef<List<MyPojo>> typeReference = new TypeRef<>() {};

final ObjectMapper mapper = new ObjectMapper().registerModule(new JavaTimeModule());

final List<MyPojo> argusMessages = JsonPath.using(
        Configuration.builder()
                .jsonProvider(new JacksonJsonProvider(mapper))
                .mappingProvider(new JacksonMappingProvider(mapper))
                .build()
    )
    .parse(responseJson)
    .read("$['aggregations']['my_agg']['buckets'][*]['latest']['hits']['hits'][0]['_source']", typeReference);

now works as expected.

To avoid other users hitting similar problems I think it would be good to have a static method like Configuration.jacksonConfiguration() that set both the json provider and the mapping provider to the Jackson classes.

shenngw1127 commented 2 years ago

@SingingBush

Thanks a lot!

add this line, i can use Jackson to deserialize the json.

.mappingProvider(new JacksonMappingProvider(mapper))