1

在我的 Spring MVC Java 应用程序中,我使用的是 Jersey REST API。我正在使用杰克逊进行 JSON 处理。我将Genson添加到我的项目中,用于过滤某些类的某些字段。我试图只为此使用Genson,剩下的我想使用Jackson。

但是我在使用 Jersey REST api 时遇到异常,因为当 Jar 位于类路径中时,默认情况下启用了 Jersey 的 Genson(从这个链接知道)。

这是我连接到 Web 服务并使用 Jackson 获取数据并转换为 String 的代码

public String connect() throws Exception {
        Client client = Client.create();
        try {
            String auth = new String(Base64.encode(userName + COLON + password));
            WebResource webResource = client
                    .resource(webServiceUrl);
            ClientResponse response = webResource
                    .header(AUTHORIZATION, BASIC + auth).type(APPLICATION_JSON)
                    .accept(APPLICATION_JSON).get(ClientResponse.class);
            //code to check response status code.
                stringResponse = response.getEntity(String.class);

        } catch (ClientHandlerException e) {
            throw new Exception("Not a Valid Url.");
        } finally {
            client.destroy();
        }
        return stringResponse;
}

我收到以下异常

javax.ws.rs.WebApplicationException: com.owlike.genson.JsonBindingException: Could not deserialize to type class java.lang.String
    at com.owlike.genson.ext.jaxrs.GensonJsonConverter.readFrom(GensonJsonConverter.java:130)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:553)
    at com.sun.jersey.api.client.ClientResponse.getEntity(ClientResponse.java:506)
    at com.myapp.WebHttpClient.connect(WebHttpClient.java:74)
    at com.myapp.connection.connectors.WebConnector.getData(WebConnector.java:39)
    at com.myapp.adapter.impl.SourceAdapter.getData(SourceAdapter.java:29)
    at com.myapp.service.impl.WebServiceImpl.adapter(WebServiceImpl.java:174)
    at com.myapp.service.impl.WebServiceImpl.connect(WebServiceImpl.java:107)
    ... 41 more
Caused by: com.owlike.genson.JsonBindingException: Could not deserialize to type class java.lang.String
    at com.owlike.genson.Genson.deserialize(Genson.java:398)
    at com.owlike.genson.ext.jaxrs.GensonJsonConverter.readFrom(GensonJsonConverter.java:128)
    ... 48 more
Caused by: com.owlike.genson.stream.JsonStreamException: Readen value can not be converted to String
    at com.owlike.genson.stream.JsonReader.valueAsString(JsonReader.java:200)
    at com.owlike.genson.convert.DefaultConverters$StringConverter.deserialize(DefaultConverters.java:364)
    at com.owlike.genson.convert.DefaultConverters$StringConverter.deserialize(DefaultConverters.java:351)
    at com.owlike.genson.convert.NullConverter$NullConverterWrapper.deserialize(NullConverter.java:56)
    at com.owlike.genson.Genson.deserialize(Genson.java:396)
    ... 49 more

第 74 行指的是 stringResponse = response.getEntity(String.class);.

如何禁用 Genson for Jersey 或如何使用 Genson 解决此问题?

谢谢

4

2 回答 2

4

The up to date documentation of Genson is hosted on github http://owlike.github.io/genson/.

What actually happens

To me it is not clear where you want to use Genson and how. Are you using Genson for serialization only? Are you using it through jersey or directly?

When you do getEntity(String.class), Jersey asks Genson to deser the incoming json to a string. Note that in general json format does not allow strings as root values.

Solutions

  1. Upgrade to jersey 2.X (and latest Genson release), in the new Jersey version when you ask the input as a string it does not delegate to MessageBodyReader (correct behaviour IMO). Then you can use this string to deser to whatever type you want.

  2. Use getEntityInputStream method from ClientResponse to get the raw InputStream and convert it to a String.

  3. Another solution would be to override Gensons implementation of MessageBodyReader, to not handle deser to String.


Having multiple libs that handle JSON conversion at the same time does not sound right to me. Especially as both (Jackson and Genson) provide some similar features. I opened an issue allowing people to disable Genson in JAX-RS apps.

Update Genson 1.3 and up provide a system to disable Genson in a Jax-RS app.

于 2015-01-21T04:53:04.937 回答
0

这是解决方案2的示例...

使用 ClientResponse 中的 getEntityInputStream 方法获取原始 InputStream 并将其转换为字符串:

private String responseString(ClientResponse response) {
    InputStream stream = response.getEntityInputStream();
    StringBuilder textBuilder = new StringBuilder();
    try (Reader reader = new BufferedReader(new InputStreamReader(stream, Charset.forName(StandardCharsets.UTF_8.name())))) {
        int c = 0;
        while ((c = reader.read()) != -1) {
            textBuilder.append((char) c);
        }
        return textBuilder.toString();
    } catch (IOException e) {
        e.printStackTrace();
        return null;
    }
}
于 2020-03-03T04:38:39.773 回答