我尝试使用MOXy设置简单的Jersey JAX-RS应用程序以支持JAXB JSON,我想自定义unmarshaller。我做了以下事情:
@Provider
public class CustomProvider extends ConfigurableMoxyJsonProvider{
@Override
protected void preReadFrom(..., Unmarshaller unmarshaller) throws JAXBException{
super.preReadFrom(...);
System.out.println("preReadFrom entered");
unmarshaller.setEventHandler(new ValidationEventHandler(){
@Override
public boolean handleEvent(ValidationEvent event){
System.out.println("Entered handleEvent");
return false;
}
});
}
}
我为preReadFrom
编写了一个覆盖,并在unmarshaller上设置了一个事件处理程序。当我传递一个无效的JSON主体时,preReadFrom
中的print语句执行但不执行事件处理程序中的print语句。因此提供程序已正确注册,但未调用事件处理程序。
可能导致此问题的原因是什么?
我想要实现的是当用户在JSON体中传递无关属性时,我想抛出一个错误(默认情况下,忽略这些属性)。在各种网站上搜索,添加事件处理程序是唯一的方法。如果我能以不同的方式实现这一点,那就太好了。
答案 0 :(得分:0)
我认为System.out.println("preReadFrom entered");
已被调用,而您的CustomProvider
实际已注册并已使用。因为在Weblogic中,即使您注册了不同的提供程序,除非您禁用Moxy,否则仍会调用默认ConfigurableMoxyJsonProvider
。
如果第一个假设是正确的,那么肯定会让public boolean handleEvent(ValidationEvent event)
调用验证,例如你的Pojo属性是数字的,你在json中传递String。
对于UnmappedElements
,我看过Moxy,"忽略" Json的警告。这意味着如果你的pojo如下所示:
public class Emp {
public Emp() {
super();
}
private int id ;
public void setId(int id) {
this.id = id;
}
public int getId() {
return id;
}
}
你的Json就像:{"id" : 11, "name1" : 111}
然后你的handleEvent
被叫了。原因是Moxy使用org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.startUnmappedElement()在向事件处理程序发出警告之前检查媒体类型是否为xml。
那么如何解决它的问题。我可能不知道最好的答案,但这是我的解决方案:
在preReadFrom
方法中添加您的自定义UnmappedHandlerClass
,如下所示
protected void preReadFrom(Class<Object> type, Type genericType, Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders,
Unmarshaller unmarshaller) throws JAXBException {
System.out.println("preReadFrom entered");
super.preReadFrom(type, genericType, annotations, MediaType.WILDCARD_TYPE, httpHeaders, unmarshaller);
System.out.println("preReadFrom returned from super");
//new code
if(unmarshaller instanceof org.eclipse.persistence.jaxb.JAXBUnmarshaller) {
org.eclipse.persistence.jaxb.JAXBUnmarshaller moxyUn = ( org.eclipse.persistence.jaxb.JAXBUnmarshaller)unmarshaller;
moxyUn.getXMLUnmarshaller().setUnmappedContentHandlerClass(CustomUnmapped.class);
}
//your existing code
unmarshaller.setEventHandler(new ValidationEventHandler() {
@Override
public boolean handleEvent(ValidationEvent event) {
System.out.println("Entered handleEvent");
return false;
}
});
}
你可以像这样使用Customunmapped类:
class CustomUnmapped extends org.eclipse.persistence.internal.oxm.unmapped.DefaultUnmappedContentHandler {
@Override
public void startElement(String p1, String p2, String p3, Attributes p4) throws SAXException {
throw new SAXNotRecognizedException(p1);
}
}
这应该有效。但在尝试3之前,只需确保通过添加断点或System.out ..语句实际调用a)CustomProvider。 b)你的handleEvent被调用一般错误,比如在json中传递一个字符串x,用于数字字段。