Jersey REST 客户端 - 将自定义 MediaType 视为 MediaType.APPLICATION_JSON
Jersey REST Client - Treat Custom MediaType as MediaType.APPLICATION_JSON
我正在使用启用了 JacksonFeature 的 Jersey 为 Web 服务编写 REST 客户端,这迫使我指定其自定义命名的内容类型,即使它只是常规 JSON.换句话说,当我这样做时:
Request request = buildMySampleRequestPojo();
Response response = requestBuilder.post(
Entity.entity(request, MediaType.APPLICATION_JSON)
);
服务抱怨我使用了无效的内容类型。我可以通过指定他们自定义命名的媒体类型来代替 MediaType.APPLICATION_JSON 常量来解决这个问题:
Response response = requestBuilder.post(
Entity.entity(request, "vnd.stupidNameThatReallyIsJustJSON+json")
);
但是,当我这样做时,我得到:
*SEVERE: MessageBodyWriter not found for media type=stupidNameThatReallyIsJustJSON*
有没有一种方法可以让 Jersey 将此自定义媒体类型名称视为常规 JSON 而无需编写自定义 MessageBodyWriter?
我认为您可以同时使用两者 this (JAX-RS entity providers) and this (use Jackson with Jersey),以实现您想要的效果。简而言之,注册一个用 @Produces("application/vnd.stupidNameThatReallyIsJustJSON+json")
注释的 MessageBodyWriter
并在实现中将 marshalling/unmarshalling 委托给 Jackson。
编辑:尝试使用
package my.pack.age;
import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider;
import com.sun.jersey.core.util.ReaderWriter;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
@Produces("application/vnd.stupidNameThatReallyIsJustJSON+json")
public class MyJsonBodyWriter<T> extends AbstractMessageReaderWriterProvider<T> {
// T should be your pojo in this case. If you can make your pojo compatible with org.codehaus.jettison.json.JSONObject,
// then you can extend com.sun.jersey.json.impl.provider.entity.JSONObjectProvider and delegate all the methods of
// MessageBodyWriter (and MessageBodyReader) to that. Otherwise just implement them.
@Override
public T readFrom(Class<T> type, Type genericType, Annotation annotations[], MediaType mediaType,MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
try {
// deserialize entityStream according to the given media type and return a new instance of T.
//
// You can do it like this (just an example) :
// JSONObject myObject = new JSONObject();
// try {
// these names and values should come from the stream.
// myObject.put("name", "Agamemnon");
// myObject.put("age", 32);
// } catch (JSONException ex) {
// LOGGER.log(Level.SEVERE, "Error ...", ex);
// }
return null;
} catch (Exception e) {
throw new WebApplicationException(new Exception("Error during deserialization", e),400);
}
}
@Override
public void writeTo(T t,Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {
try {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, ReaderWriter.getCharset(mediaType));
// write t on the writer
writer.flush();
} catch (Exception e) {
throw new WebApplicationException( new Exception("Error during serialization", e), 500);
}
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// should return true if this class can serialize the given type to the given media type
return true;
}
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// should return true if this class can deserialize the given type to the given media type
return true;
}
@Override
public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// calculate and return content-lenght, i.e. the lenght of the serialized representation of t
return 0;
}
}
显然这只是一个起点,不是一个工作示例,但它应该为您提供足够的信息来开始。还要记住,您必须将 class 注册到 Jersey 才能使用它。
我正在使用启用了 JacksonFeature 的 Jersey 为 Web 服务编写 REST 客户端,这迫使我指定其自定义命名的内容类型,即使它只是常规 JSON.换句话说,当我这样做时:
Request request = buildMySampleRequestPojo();
Response response = requestBuilder.post(
Entity.entity(request, MediaType.APPLICATION_JSON)
);
服务抱怨我使用了无效的内容类型。我可以通过指定他们自定义命名的媒体类型来代替 MediaType.APPLICATION_JSON 常量来解决这个问题:
Response response = requestBuilder.post(
Entity.entity(request, "vnd.stupidNameThatReallyIsJustJSON+json")
);
但是,当我这样做时,我得到:
*SEVERE: MessageBodyWriter not found for media type=stupidNameThatReallyIsJustJSON*
有没有一种方法可以让 Jersey 将此自定义媒体类型名称视为常规 JSON 而无需编写自定义 MessageBodyWriter?
我认为您可以同时使用两者 this (JAX-RS entity providers) and this (use Jackson with Jersey),以实现您想要的效果。简而言之,注册一个用 @Produces("application/vnd.stupidNameThatReallyIsJustJSON+json")
注释的 MessageBodyWriter
并在实现中将 marshalling/unmarshalling 委托给 Jackson。
编辑:尝试使用
package my.pack.age;
import com.sun.jersey.core.provider.AbstractMessageReaderWriterProvider;
import com.sun.jersey.core.util.ReaderWriter;
import javax.ws.rs.Produces;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
@Produces("application/vnd.stupidNameThatReallyIsJustJSON+json")
public class MyJsonBodyWriter<T> extends AbstractMessageReaderWriterProvider<T> {
// T should be your pojo in this case. If you can make your pojo compatible with org.codehaus.jettison.json.JSONObject,
// then you can extend com.sun.jersey.json.impl.provider.entity.JSONObjectProvider and delegate all the methods of
// MessageBodyWriter (and MessageBodyReader) to that. Otherwise just implement them.
@Override
public T readFrom(Class<T> type, Type genericType, Annotation annotations[], MediaType mediaType,MultivaluedMap<String, String> httpHeaders, InputStream entityStream) throws IOException {
try {
// deserialize entityStream according to the given media type and return a new instance of T.
//
// You can do it like this (just an example) :
// JSONObject myObject = new JSONObject();
// try {
// these names and values should come from the stream.
// myObject.put("name", "Agamemnon");
// myObject.put("age", 32);
// } catch (JSONException ex) {
// LOGGER.log(Level.SEVERE, "Error ...", ex);
// }
return null;
} catch (Exception e) {
throw new WebApplicationException(new Exception("Error during deserialization", e),400);
}
}
@Override
public void writeTo(T t,Class<?> type, Type genericType, Annotation annotations[], MediaType mediaType, MultivaluedMap<String, Object> httpHeaders, OutputStream entityStream) throws IOException {
try {
OutputStreamWriter writer = new OutputStreamWriter(entityStream, ReaderWriter.getCharset(mediaType));
// write t on the writer
writer.flush();
} catch (Exception e) {
throw new WebApplicationException( new Exception("Error during serialization", e), 500);
}
}
@Override
public boolean isWriteable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// should return true if this class can serialize the given type to the given media type
return true;
}
@Override
public boolean isReadable(Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// should return true if this class can deserialize the given type to the given media type
return true;
}
@Override
public long getSize(T t, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
// calculate and return content-lenght, i.e. the lenght of the serialized representation of t
return 0;
}
}
显然这只是一个起点,不是一个工作示例,但它应该为您提供足够的信息来开始。还要记住,您必须将 class 注册到 Jersey 才能使用它。