[英]Jersey JSON serialization with external classes
我正在尝试在我的石英调度程序上创建一个rest api服务器。 我希望能够将org.quartz.Trigger和org.quartz.JobDetail对象作为JSON返回。 问题是我不能将@XmlRootElement添加到这些类而不必重新编译jar,这会导致将来的升级等问题。我已经测试并且能够在添加@XmlRootElement时序列化类列表但是当我尝试返回一个List我收到错误“Java类java.util.ArrayList的消息体编写器,Java类型java.util.List,找不到MIME媒体类型application / json”。 我尝试添加自定义MessageBodyWriter,但似乎也没有解决问题。 有没有办法将石英类编组为JSON,而无需修改石英代码来添加@XmlRootElement。 我在带有jetty btw的嵌入式web服务器中使用它。
@Path("/jobs")
public class JobsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public List<Trigger> listScheduledJobs() throws SchedulerException {
return TaskEngine.getInstance().listScheduledJobs();
}
}
Web服务器配置
public class TaskEngineWebServer {
private static final Logger logger = Logger.getLogger(TaskEngineWebServer.class.getName());
private Server server;
public TaskEngineWebServer() {
this(8585);
}
public TaskEngineWebServer(Integer port) {
server = new Server(port);
logger.info("Configuring rest service to start at url /r");
ServletContextHandler handler = new ServletContextHandler(ServletContextHandler.NO_SECURITY);
//handler.getInitParams().put("com.sun.jersey.api.json.POJOMappingFeature", "true");
PackagesResourceConfig packagesResourceConfig = new PackagesResourceConfig("com.hp.vf.scheduler.server.rest");
ServletContainer servletContainer = new ServletContainer(packagesResourceConfig);
handler.addServlet(new ServletHolder(servletContainer), "/r/*");
server.setHandler(handler);
logger.info("Done configuring rest service");
}
public void start() throws Exception {
server.start();
}
public void stop() throws Exception {
server.stop();
}
public boolean isStarted() {
return server.isStarted();
}
public boolean isStopped() {
return server.isStopped();
}
}
我不认为你可以直接返回List作为JSON。 您需要一个包含此列表的包装类。 例如尝试这样的事情
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class TriggerWrapper{
private List<Triggers> triggers;
public List<Triggers> getTriggers(){
if(triggers==null){
triggers = new ArrayList<Triggers>();
}
return triggers;
}
}
然后在你的休息服务类:
@Path("/jobs")
public class JobsResource {
@GET
@Produces(MediaType.APPLICATION_JSON)
public TriggerWrapper listScheduledJobs() throws SchedulerException {
TriggerWrapper response = new TriggerWrapper();
List<Triggers> triggers = TaskEngine.getInstance().listScheduledJobs();
response.getTriggers.addAll(triggers);
return response;
}
}
你的json会是这样的:
{
"triggerwrapper": {
"triggers": [
{
"triggerid": 1
},
{
"triggerid": 2
}
]
}
}
当然,如果你想要你可以从你的json中删除根元素标签,它可以在球衣中配置。
我终于找到了一个干净的解决方案,它涉及创建我自己的MediaBodyWriter类并将其添加为提供者。 你必须确保你没有使用jersey-bundle jar,因为默认的jaxb到json提供者会覆盖你的。
需要罐子
jersey-core jersey-servlet jersey-server
jackson-annotations jackson-databind jackson-core
我在网上找到了这个MediaWriter示例。 很抱歉没有网址,但感谢谁写的。
@Provider
@Produces({ MediaType.APPLICATION_JSON })
public class JacksonWriter implements MessageBodyWriter<Object> {
private static final ObjectMapper MAPPER = new ObjectMapper();
@Override
public boolean isWriteable(Class<?> aClass, Type type, Annotation[] annotations, MediaType mediaType) {
return true;
}
@Override
public long getSize(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType) {
return -1;
}
@Override
public void writeTo(Object value, Class<?> type, Type genericType, Annotation[] annotations, MediaType mediaType, MultivaluedMap<String, Object> httpHeaders,
OutputStream entityStream) {
try {
MAPPER.writeValue(entityStream, value);
} catch (IOException ex) {
throw new RuntimeException(ex);
}
}
}
加载时,您将看到加载提供程序的日志消息。
这给了我期望的json输出,因为它不依赖于JAXB注释而只是使用对象映射器/反射。 效率可能不高,但就我而言,这并不重要。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.