如何使用Jersey和Jackson处理不服从的web服务:application / json

时间:2016-04-03 02:10:24

标签: java json jersey jackson

我正在使用Jersey和Jackson访问REST Web服务,该服务正确地返回格式良好的JSON数据但具有响应头:

  

Content-Type:text / html;字符集= UTF-8

即使我在请求标头中指定了Accept:application / json,结果导致Jersey抛出:

  

org.glassfish.jersey.message.internal.MessageBodyProviderNotFoundException:找不到媒体类型= text / html; charset = UTF-8

的MessageBodyReader

我使用我的代码很好地使用其他Web服务,但我想知道是否有办法创建我自己的MessageBodyReader来处理不匹配,但我还没有弄清楚如何正确实现它。我计划要求网络服务的所有者解决不匹配问题,但我并不抱太大希望。

2 个答案:

答案 0 :(得分:1)

好的,所以我设法通过基本上遵循斯蒂芬C的建议来解决这个问题,但我想我会发布更多细节,以防其他人在同一条船上。首先,我实际上从泽西指南开始了几个部分,特别是这一部分:

https://jersey.java.net/documentation/latest/user-guide.html#d0e6825

显然我使用Jersey作为javax.ws.rs.client,我使用Genson进行JSON反序列化。因此,我实现了以下类来实现MessageBodyReader:

public class BTCEURTradeMessageBodyReader 
        implements MessageBodyReader<BTCEURTrades> {

  final org.slf4j.Logger logger = 
          LoggerFactory.getLogger(BTCEURTradeMessageBodyReader.class);

  @Override
  public boolean isReadable(Class<?> type, Type genericType, 
          Annotation[] annotations, MediaType mediaType) {
    logger.info("isReadable being checked for: {} and media type: {}", type, mediaType);
    return type == BTCEURTrades.class;
  }

  @Override
  public BTCEURTrades readFrom(Class<BTCEURTrades> type, Type genericType, 
          Annotation[] annotations, MediaType mediaType, 
          MultivaluedMap<String, String> httpHeaders, InputStream entityStream) 
          throws IOException, WebApplicationException {
    logger.info("readFrom being called for: {}", type);

    BTCEURTrades btceurTrades;
    try {
      btceurTrades = new Genson().deserialize(entityStream, type);
    } catch(Exception e) {
      logger.error("Error processing JSON reponse.", e);
      throw new ProcessingException("Error processing JSON reponse.");
    }
    return btceurTrades;
  }

}

然后在客户端创建后注册,如下所示:

client = ClientBuilder.newClient();
client.register(BTCEURTradeMessageBodyReader.class);

答案 1 :(得分:0)

  

我想知道是否有办法创建我自己的MessageBodyReader来处理不匹配。

Jersey文档中的此页面介绍了如何创建自定义MessageBodyReader:

在您的情况下,您可能能够找到通常用于JSON的阅读器的源代码,并且&#34;调整&#34;它。从理论上讲。

然而,经过多一点阅读后,我发现了这个:

告诉我,泽西岛已经广泛支持JSON。你可以通过简单地调整配置来解决你的问题,以便泽西知道如何处理不寻常的内容类型。但这取决于您目前正在解析JSON响应主体的许多可能方式中的哪一种。

有人评论说:

  

我认为只是检索数据更容易,忽略标题并将其解析为json对象。

这是一个坏主意。标题告诉您JSON可以包含多字节字符。如果您只是忽略它并将字节解码为默认字符集中的字符,那么您将获得&#34; mojibake&#34;如果存在多字节字符。

如果您自己解析JSON,那么将解析器的输入流配置为使用UTF-8,或者内容类型标题所说的字符编码是其他任何内容都应该是一件简单的事情。

最后,问题是&#34;谁错了&#34;。

我其实认为这是你的错。如果您只发送一个&#34;接受:application / json&#34;标题,您告诉服务器您不关心字符集是什么。然后,服务器可以自由地为其知道将正确表示响应文本的响应选择任何字符集。 (在本例中是JSON的文本内容。)

如果您特别想要(比方说)ASCII或Latin-1,那么您应该添加一个&#34; Accept-charset:&#34;报头中。

如果&gt;&gt; THAT&lt;&lt;没有工作,那么也许这是服务器的错。但请记住,如果响应确实/可能包含无法在您首选的字符集上编码的字符,那么服务器可能/应该向您发送406错误。