我已经把头发拉了好几天。我无法弄清楚发生了什么。我正在使用GWT开发WebApp,它使用RestAPI与不同的服务器通信。我使用Jersey客户端与GWT项目的Server部分中的不同服务器进行通信。
基本上,我遇到了Jackson解析从RestAPI服务器返回的JSON的问题。它正在解析的JSON对象在Android应用程序以及IOS应用程序中成功使用,而RestAPI服务器没有任何问题。
基本上,为了调试这个问题,我拿出Jersey媒体插件并让jersey返回一个对象的字符串,然后将字符串传递给ObjectMapper。我使用的是最新的Jackson版本2.4.4。
我有一个自定义反序列化器,它使用日期格式,我收到的错误始终是这个日期。原始JSON看起来很好,但Jackson对象映射器抛出错误。错误并不总是在相同的位置,但始终与lastInspectionDate。错误有时说字符串是空的,它试图解析,或者字符串是一些奇怪的值。
以下是一些希望澄清的代码:
它在解析时遇到问题的EstablishmentEntity类:
@JsonIgnoreProperties(ignoreUnknown = true)
public class EstablishmentEntity {
private long id;
public long getId() {
return id;
}
public void setId(long id) {
this.id = id;
}
private String establishmentName;
public String getEstablishmentName() {
return establishmentName;
}
public void setEstablishmentName(String establishmentName) {
this.establishmentName = establishmentName;
}
private String address;
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
private String city;
public String getCity() {
return city;
}
public void setCity(String city) {
this.city = city;
}
private String county;
public String getCounty() {
return county;
}
public void setCounty(String county) {
this.county = county;
}
private String stateOrProvince;
public String getStateOrProvince() {
return stateOrProvince;
}
public void setStateOrProvince(String stateOrProvince) {
this.stateOrProvince = stateOrProvince;
}
private String postalCode;
public String getPostalCode() {
return postalCode;
}
public void setPostalCode(String postalCode) {
this.postalCode = postalCode;
}
private String telephone;
public String getTelephone() {
return telephone;
}
public void setTelephone(String telephone) {
this.telephone = telephone;
}
private String establishmentType;
public String getEstablishmentType() {
return establishmentType;
}
public void setEstablishmentType(String establishmentType) {
this.establishmentType = establishmentType;
}
@JsonSerialize(using = JsonDateOnlySerializer.class)
@JsonDeserialize(using = JsonDateOnlyDeserializer.class)
private Date lastInspectionDate;
public Date getLastInspectionDate() {
return lastInspectionDate;
}
public void setLastInspectionDate(Date lastInspectionDate) {
this.lastInspectionDate = lastInspectionDate;
}
private String lastInspectionScore;
public String getLastInspectionScore() {
return lastInspectionScore;
}
public void setLastInspectionScore(String lastInspectionScore) {
this.lastInspectionScore = lastInspectionScore;
}
@JsonSerialize(using = JsonDateOnlySerializer.class)
@JsonDeserialize(using = JsonDateOnlyDeserializer.class)
private Date lastInspectionScoreDate;
public Date getLastInspectionScoreDate() {
return lastInspectionScoreDate;
}
public void setLastInspectionScoreDate(Date lastInspectionScoreDate) {
this.lastInspectionScoreDate = lastInspectionScoreDate;
}
private String lastInspectionGrade;
public String getLastInspectionGrade() {
return lastInspectionGrade;
}
public void setLastInspectionGrade(String lastInspectionGrade) {
this.lastInspectionGrade = lastInspectionGrade;
}
@JsonSerialize(using = JsonDateOnlySerializer.class)
@JsonDeserialize(using = JsonDateOnlyDeserializer.class)
private Date lastInspectionGradeDate;
public Date getLastInspectionGradeDate() {
return lastInspectionGradeDate;
}
public void setLastInspectionGradeDate(Date lastInspectionGradeDate) {
this.lastInspectionGradeDate = lastInspectionGradeDate;
}
private String healthDepartment;
public String getHealthDepartment() {
return healthDepartment;
}
public void setHealthDepartment(String healthDepartment) {
this.healthDepartment = healthDepartment;
}
private boolean lastInspectionCritical;
public boolean isLastInspectionCritical() {
return lastInspectionCritical;
}
public void setLastInspectionCritical(boolean lastInspectionCritical) {
this.lastInspectionCritical = lastInspectionCritical;
}
private boolean lastInspectionPriority;
public boolean isLastInspectionPriority() {
return lastInspectionPriority;
}
public void setLastInspectionPriority(boolean lastInspectionPriority) {
this.lastInspectionPriority = lastInspectionPriority;
}
private boolean lastInspectionPriorityFoundation;
public boolean isLastInspectionPriorityFoundation() {
return lastInspectionPriorityFoundation;
}
public void setLastInspectionPriorityFoundation(boolean lastInspectionPriorityFoundation) {
this.lastInspectionPriorityFoundation = lastInspectionPriorityFoundation;
}
private double latitude;
public double getLatitude() {
return latitude;
}
public void setLatitude(double latitude) {
this.latitude = latitude;
}
private double longitude;
public double getLongitude() {
return longitude;
}
public void setLongitude(double longitude) {
this.longitude = longitude;
}
private Timestamp added;
public Timestamp getAdded() {
return added;
}
public void setAdded(Timestamp added) {
this.added = added;
}
private String geocoder;
public String getGeocoder() {
return geocoder;
}
public void setGeocoder(String geocoder) {
this.geocoder = geocoder;
}
private String geocoderVersion;
public String getGeocoderVersion() {
return geocoderVersion;
}
public void setGeocoderVersion(String geocoderVersion) {
this.geocoderVersion = geocoderVersion;
}
private Double hdscoreRankingPercent;
public Double getHdscoreRankingPercent() {
return hdscoreRankingPercent;
}
public void setHdscoreRankingPercent(Double hdscoreRankingPercent) {
this.hdscoreRankingPercent = hdscoreRankingPercent;
}
private String hdscoreProvider;
public String getHdscoreProvider() {
return hdscoreProvider;
}
public void setHdscoreProvider(String hdscoreProvider) {
this.hdscoreProvider = hdscoreProvider;
}
private Double hdscore;
public Double getHdscore() {
return hdscore;
}
public void setHdscore(Double hdscore) {
this.hdscore = hdscore;
}
private String hdscoreVersion;
public String getHdscoreVersion() {
return hdscoreVersion;
}
public void setHdscoreVersion(String hdscoreVersion) {
this.hdscoreVersion = hdscoreVersion;
}
}
JSON反序列化器:
public class JsonDateOnlyDeserializer extends JsonDeserializer<Date> {
private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
String dateString = jp.getText();
try {
return dateFormat.parse(dateString);
}
catch (ParseException e) {
throw new RuntimeException(e);
}
}
}
Raw JSON示例(由于长度而中断):
{
"responseId":1,
"resultsLimited":true,
"totalResults":485651,
"geoHashLevel":2,
"items":[
{
"establishmentEntity":{
"id":469715,
"establishmentName":"PENNY'S KITCHEN",
"address":"822 W 14th St",
"city":"Coffeyville",
"county":"Montgomery",
"stateOrProvince":"KS",
"postalCode":"67337-4402",
"telephone":"9183317321",
"establishmentType":null,
"lastInspectionScore":null,
"lastInspectionGrade":null,
"healthDepartment":"State of Kansas",
"lastInspectionCritical":false,
"lastInspectionPriority":false,
"lastInspectionPriorityFoundation":false,
"latitude":37.02878,
"longitude":-95.625374,
"added":1409016435000,
"geocoder":"com.hdscores.inspection.source.geocoding.MapQuestLicensedGeocoder",
"geocoderVersion":"1.12",
"hdscoreRankingPercent":0.301823675,
"hdscoreProvider":"com.hdscores.inspection.hdscore.ViolationsHDScoreProvider",
"hdscore":4.373924497631436,
"hdscoreVersion":"1.04",
"lastInspectionDate":"2013-10-17",
"lastInspectionScoreDate":null,
"lastInspectionGradeDate":null
},
"preferredLevel":0,
"logoUrl":null,
"resultsTop":false,
"resultsBottom":false,
"featured":false,
"reportsViolations":true,
"displayName":"PENNY'S KITCHEN"
},
{
"establishmentEntity":{
"id":281253,
"establishmentName":"COFFEYVILLE LIVESTOCK MARKET",
"address":"822 W 14th St",
"city":"Coffeyville",
"county":"Montgomery",
"stateOrProvince":"KS",
"postalCode":"67337-4402",
"telephone":"6202515460",
"establishmentType":null,
"lastInspectionScore":null,
"lastInspectionGrade":null,
"healthDepartment":"State of Kansas",
"lastInspectionCritical":true,
"lastInspectionPriority":false,
"lastInspectionPriorityFoundation":false,
"latitude":37.02878,
"longitude":-95.625374,
"added":1405623496000,
"geocoder":"com.hdscores.inspection.source.geocoding.MapQuestLicensedGeocoder",
"geocoderVersion":"1.12",
"hdscoreRankingPercent":0.133052767,
"hdscoreProvider":"com.hdscores.inspection.hdscore.ViolationsHDScoreProvider",
"hdscore":6.5,
"hdscoreVersion":"1.04",
"lastInspectionDate":"2011-06-23",
"lastInspectionScoreDate":null,
"lastInspectionGradeDate":null
},
"preferredLevel":0,
"logoUrl":null,
"resultsTop":false,
"resultsBottom":false,
"featured":false,
"reportsViolations":true,
"displayName":"COFFEYVILLE LIVESTOCK MARKET"
},
{
"establishmentEntity":{
"id":368166,
"establishmentName":"TROPICAL SNO",
"address":"823 E 11th St",
"city":"Coffeyville",
"county":"Montgomery",
"stateOrProvince":"KS",
"postalCode":"67337-6603",
"telephone":"6203303296",
"establishmentType":null,
"lastInspectionScore":null,
"lastInspectionGrade":null,
"healthDepartment":"State of Kansas",
"lastInspectionCritical":false,
"lastInspectionPriority":false,
"lastInspectionPriorityFoundation":false,
"latitude":37.032937,
"longitude":-95.602057,
"added":1406367309000,
"geocoder":"com.hdscores.inspection.source.geocoding.MapQuestLicensedGeocoder",
"geocoderVersion":"1.12",
"hdscoreRankingPercent":0.449228445,
"hdscoreProvider":"com.hdscores.inspection.hdscore.ViolationsHDScoreProvider",
"hdscore":3.3172017928863275,
"hdscoreVersion":"1.04",
"lastInspectionDate":"2013-04-04",
"lastInspectionScoreDate":null,
"lastInspectionGradeDate":null
},
"preferredLevel":1,
"logoUrl":null,
"resultsTop":false,
"resultsBottom":false,
"featured":false,
"reportsViolations":true,
"displayName":"TROPICAL SNO"
},
{
"establishmentEntity":{
"id":494794,
"establishmentName":"SIR VON II",
"address":"806 E 11th St",
"city":"Coffeyville",
"county":"Montgomery",
"stateOrProvince":"KS",
"postalCode":"67337-6604",
"telephone":"6206886321",
"establishmentType":null,
"lastInspectionScore":null,
"lastInspectionGrade":null,
"healthDepartment":"State of Kansas",
"lastInspectionCritical":true,
"lastInspectionPriority":false,
"lastInspectionPriorityFoundation":false,
"latitude":37.032902,
"longitude":-95.604437,
"added":1410044780000,
"geocoder":"com.hdscores.inspection.source.geocoding.MapQuestLicensedGeocoder",
"geocoderVersion":"1.12",
"hdscoreRankingPercent":0.195856264,
"hdscoreProvider":"com.hdscores.inspection.hdscore.ViolationsHDScoreProvider",
"hdscore":5.5,
"hdscoreVersion":"1.04",
"lastInspectionDate":"2012-07-30",
"lastInspectionScoreDate":null,
"lastInspectionGradeDate":null
},
"preferredLevel":0,
"logoUrl":null,
"resultsTop":false,
"resultsBottom":false,
"featured":false,
"reportsViolations":true,
"displayName":"SIR VON II"
},
{
"establishmentEntity":{
"id":377960,
"establishmentName":"DAYS INN",
"address":"820 E 11th St",
"city":"Coffeyville",
"county":"Montgomery",
"stateOrProvince":"KS",
"postalCode":"67337-6604",
"telephone":"6202510002",
"establishmentType":null,
"lastInspectionScore":null,
"lastInspectionGrade":null,
"healthDepartment":"State of Kansas",
"lastInspectionCritical":false,
"lastInspectionPriority":false,
"lastInspectionPriorityFoundation":false,
"latitude":37.0329,
"longitude":-95.60475,
"added":1406692555000,
"geocoder":"com.hdscores.inspection.source.geocoding.MapQuestLicensedGeocoder",
"geocoderVersion":"1.12",
"hdscoreRankingPercent":0.6747599,
"hdscoreProvider":"com.hdscores.inspection.hdscore.ViolationsHDScoreProvider",
"hdscore":2.0,
"hdscoreVersion":"1.04",
"lastInspectionDate":"2013-12-24",
"lastInspectionScoreDate":null,
"lastInspectionGradeDate":null
},
"preferredLevel":1,
"logoUrl":null,
"resultsTop":false,
"resultsBottom":false,
"featured":false,
"reportsViolations":true,
"displayName":"DAYS INN"
},
{
"establishmentEntity":{
"id":119641,
"establishmentName":"SIRLOIN STOCKADE",
"address":"104 W 11th St",
"city":"Coffeyville",
"county":"Montgomery",
"stateOrProvince":"KS",
"postalCode":"67337-5902",
"telephone":"6202518156",
"establishmentType":null,
"lastInspectionScore":null,
"lastInspectionGrade":null,
"healthDepartment":"State of Kansas",
"lastInspectionCritical":false,
"lastInspectionPriority":false,
"lastInspectionPriorityFoundation":false,
"latitude":37.03298,
"longitude":-95.615787,
"added":1400599518000,
"geocoder":"com.hdscores.inspection.source.geocoding.MapQuestGeocoder",
"geocoderVersion":"1.00",
"hdscoreRankingPercent":0.147512679,
"hdscoreProvider":"com.hdscores.inspection.hdscore.ViolationsHDScoreProvider",
"hdscore":6.209693418399466,
"hdscoreVersion":"1.04",
"lastInspectionDate":"2014-03-07",
"lastInspectionScoreDate":null,
"lastInspectionGradeDate":null
},
"preferredLevel":0,
"logoUrl":null,
"resultsTop":false,
"resultsBottom":false,
"featured":false,
"reportsViolations":true,
"displayName":"SIRLOIN STOCKADE"
},
以下是我多次重复运行相同代码的一些错误:
java.lang.RuntimeException: com.fasterxml.jackson.databind.JsonMappingException: multiple points (through reference chain: com.hdscores.consumer.service.client.SearchResponse["items"]->java.util.ArrayList[0]->com.hdscores.consumer.service.client.Establishment["establishmentEntity"]->com.hdscores.consumer.service.client.EstablishmentEntity["lastInspectionDate"])
(Removed intermediate errors)
Caused by: java.lang.NumberFormatException: multiple points
at sun.misc.FloatingDecimal.readJavaFormatString(FloatingDecimal.java:1101)
at java.lang.Double.parseDouble(Double.java:540)
at java.text.DigitList.getDouble(DigitList.java:168)
at java.text.DecimalFormat.parse(DecimalFormat.java:1321)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:2088)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.hdscores.consumer.service.client.JsonDateOnlyDeserializer.deserialize(JsonDateOnlyDeserializer.java:23)
at com.hdscores.consumer.service.client.JsonDateOnlyDeserializer.deserialize(JsonDateOnlyDeserializer.java:16)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:538)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:99)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:238)
... 51 more
有时这是错误......
Caused by: java.lang.NumberFormatException: For input string: "5E51"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:65)
at java.lang.Long.parseLong(Long.java:441)
at java.lang.Long.parseLong(Long.java:483)
at java.text.DigitList.getLong(DigitList.java:194)
at java.text.DecimalFormat.parse(DecimalFormat.java:1316)
at java.text.SimpleDateFormat.subParse(SimpleDateFormat.java:1793)
at java.text.SimpleDateFormat.parse(SimpleDateFormat.java:1455)
at java.text.DateFormat.parse(DateFormat.java:355)
at com.hdscores.consumer.service.client.JsonDateOnlyDeserializer.deserialize(JsonDateOnlyDeserializer.java:23)
at com.hdscores.consumer.service.client.JsonDateOnlyDeserializer.deserialize(JsonDateOnlyDeserializer.java:16)
at com.fasterxml.jackson.databind.deser.SettableBeanProperty.deserialize(SettableBeanProperty.java:538)
at com.fasterxml.jackson.databind.deser.impl.MethodProperty.deserializeAndSet(MethodProperty.java:99)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.vanillaDeserialize(BeanDeserializer.java:238)
它的疯狂,有时它没有错误,有时它没有......
任何帮助,将不胜感激....
答案 0 :(得分:7)
我明白了!我发现SimpleDateFormat不是线程安全的,所以我为每个线程创建了一个新实例并更新了我的JSON反序列化器:
public class JsonDateOnlyDeserializer extends JsonDeserializer<Date> {
//private static final SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
@Override
public Date deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
String dateString = jp.getText();
try {
return dateFormat.parse(dateString);
}
catch (ParseException e) {
throw new RuntimeException(e);
}
}
}