我正在编写一个简单的地理编码应用程序,使用Jersey REST客户端api,它使用OpenStreetMap / Mapquest Nominatim REST服务。调用返回类似于此的JSON响应:
[ {
"place_id":"249137377",
"licence":"Data \u00a9 OpenStreetMap contributors, ODbL 1.0. http:\/\/www.openstreetmap.org\/copyright",
"boundingbox":["32.834854904644","32.834954904644","-79.243545952863","-79.243445952863"],
"lat":"32.8349049046436",
"lon":"-79.2434959528633",
"display_name":"9000, Maple Avenue, Bedford, Trimble County, Kentucky, 40006, United States of America",
"class":"place",
"type":"house",
"importance":0.521
} ]
如您所见,它包含一个名为type
的字段。在解组此JSON响应时,会引发以下异常:
Caused by: Exception [EclipseLink-43] (Eclipse Persistence Services - 2.5.1.v20130918-f2b9fc5): org.eclipse.persistence.exceptions.DescriptorException
Exception Description: Missing class for indicator field value [house] of type [class java.lang.String].
Descriptor: XMLDescriptor(com.edc.c2c.geospatial.nominatim.v1.model.impl.NominatimResponse --> [])
at org.eclipse.persistence.exceptions.DescriptorException.missingClassForIndicatorFieldValue(DescriptorException.java:940)
at org.eclipse.persistence.internal.oxm.QNameInheritancePolicy.classFromRow(QNameInheritancePolicy.java:266)
at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.classFromRow(TreeObjectBuilder.java:182)
at org.eclipse.persistence.internal.oxm.TreeObjectBuilder.classFromRow(TreeObjectBuilder.java:1)
at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.initializeRecord(UnmarshalRecordImpl.java:502)
at org.eclipse.persistence.internal.oxm.record.UnmarshalRecordImpl.startElement(UnmarshalRecordImpl.java:740)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parseRoot(JSONReader.java:177)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parseRoot(JSONReader.java:195)
at org.eclipse.persistence.internal.oxm.record.json.JSONReader.parse(JSONReader.java:125)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:972)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:425)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:635)
at org.eclipse.persistence.internal.oxm.record.SAXUnmarshaller.unmarshal(SAXUnmarshaller.java:703)
at org.eclipse.persistence.oxm.XMLUnmarshaller.unmarshal(XMLUnmarshaller.java:655)
at org.eclipse.persistence.jaxb.JAXBUnmarshaller.unmarshal(JAXBUnmarshaller.java:301)
at org.eclipse.persistence.jaxb.rs.MOXyJsonProvider.readFrom(MOXyJsonProvider.java:597)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor$TerminalReaderInterceptor.aroundReadFrom(ReaderInterceptorExecutor.java:188)
at org.glassfish.jersey.message.internal.ReaderInterceptorExecutor.proceed(ReaderInterceptorExecutor.java:134)
at org.glassfish.jersey.message.internal.MessageBodyFactory.readFrom(MessageBodyFactory.java:988)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:833)
at org.glassfish.jersey.message.internal.InboundMessageContext.readEntity(InboundMessageContext.java:768)
at org.glassfish.jersey.client.InboundJaxrsResponse.readEntity(InboundJaxrsResponse.java:96)
at org.glassfish.jersey.client.JerseyInvocation.translate(JerseyInvocation.java:761)
... 31 more
我推测错误正在发生,因为type
被视为一种类鉴别器,house
被解释为子类而不是简单的字符串。
这是用于调用服务的代码:
public Coordinate lookup( StreetAddress a_StreetAddress )
{
LatLongCoordinate result = null ;
Client client = ClientBuilder.newClient() ;
client.register( MoxyXmlFeature.class ) ;
WebTarget target = client.target( this.getEndPointUrl() ) ;
NominatimResponse response =
target
.queryParam( "q", a_StreetAddress.format() ) // Buildup GET request
.queryParam( "format", "json" )
.queryParam( "addressdetails", "0" )
.queryParam( "limit", "1" )
.request( MediaType.APPLICATION_JSON_TYPE ) // Only accept JSON back in response
.buildGet()
.invoke( NominatimResponse.class )
;
if ( ( response != null ) && ( response.getLatitude() != null ) && ( response.getLongitude() != null ) ) {
result = new LatLongCoordinate( response.getLatitude(), response.getLongitude() ) ;
}
return result ;
}
这是我创建的NominatimResponse
类,用于将响应解组为:
public class NominatimResponse extends AbstractGeospatialModelObject
{
private static final long serialVersionUID = -7514888439468843335L ;
@XmlElement( name = "place_id" )
private String m_PlaceId = null ;
@XmlElement( name = "license" )
private String m_License = null ;
@XmlElement( name = "osm_type" )
private String m_OsmType = null ;
@XmlElement( name = "osm_id" )
private String m_OsmId = null ;
@XmlElement( name = "bounding_box")
private Double[] m_BoundingBox = null ;
@XmlElement( name = "lat" )
private Double m_Latitude = null ;
@XmlElement( name = "lon" )
private Double m_Longitude = null ;
@XmlElement( name = "display_name" )
private String m_DisplayName = null ;
@XmlElement( name = "class" )
private String m_Classifier = null ;
@XmlElement( name = "type" )
private String m_Type = null ;
@XmlElement( name = "importance" )
private Double m_Importance = null ;
/**
* @return the placeId
*/
public String getPlaceId()
{
return this.m_PlaceId ;
}
/**
* @param a_placeId the placeId to set
*/
public void setPlaceId( String a_placeId )
{
this.m_PlaceId = a_placeId ;
}
/**
* @return the license
*/
public String getLicense()
{
return this.m_License ;
}
/**
* @param a_license the license to set
*/
public void setLicense( String a_license )
{
this.m_License = a_license ;
}
/**
* @return the osmType
*/
public String getOsmType()
{
return this.m_OsmType ;
}
/**
* @param a_osmType the osmType to set
*/
public void setOsmType( String a_osmType )
{
this.m_OsmType = a_osmType ;
}
/**
* @return the osmId
*/
public String getOsmId()
{
return this.m_OsmId ;
}
/**
* @param a_osmId the osmId to set
*/
public void setOsmId( String a_osmId )
{
this.m_OsmId = a_osmId ;
}
/**
* @return the boundingBox
*/
public Double[] getBoundingBox()
{
return this.m_BoundingBox ;
}
/**
* @param a_boundingBox the boundingBox to set
*/
public void setBoundingBox( Double[] a_boundingBox )
{
this.m_BoundingBox = a_boundingBox ;
}
/**
* @return the latitude
*/
public Double getLatitude()
{
return this.m_Latitude ;
}
/**
* @param a_latitude the latitude to set
*/
public void setLatitude( Double a_latitude )
{
this.m_Latitude = a_latitude ;
}
/**
* @return the longitude
*/
public Double getLongitude()
{
return this.m_Longitude ;
}
/**
* @param a_longitude the longitude to set
*/
public void setLongitude( Double a_longitude )
{
this.m_Longitude = a_longitude ;
}
/**
* @return the displayName
*/
public String getDisplayName()
{
return this.m_DisplayName ;
}
/**
* @param a_displayName the displayName to set
*/
public void setDisplayName( String a_displayName )
{
this.m_DisplayName = a_displayName ;
}
/**
* @return the classifier
*/
public String getClassifier()
{
return this.m_Classifier ;
}
/**
* @param a_classifier the classifier to set
*/
public void setClassifier( String a_classifier )
{
this.m_Classifier = a_classifier ;
}
/**
* @return the type
*/
public String getType()
{
return this.m_Type ;
}
/**
* @param a_type the type to set
*/
public void setType( String a_type )
{
this.m_Type = a_type ;
}
/**
* @return the importance
*/
public Double getImportance()
{
return this.m_Importance ;
}
/**
* @param a_importance the importance to set
*/
public void setImportance( Double a_importance )
{
this.m_Importance = a_importance ;
}
}
有没有办法阻止MOXy以type
的方式对待它?似乎它需要与@XmlDiscriminatorNode
等相反。
提前感谢您的帮助。
答案 0 :(得分:0)
我遇到了同样的问题。我从Moxy换到杰克逊,杰克逊似乎正好处理这个案子。
只需更改构建脚本中的 jersey-media 依赖关系
即可// remove this
compile 'org.glassfish.jersey.media:jersey-media-moxy:2.13'
// add this
compile 'org.glassfish.jersey.media:jersey-media-json-jackson:2.13'