Проблема обработки Джексона

Я тянул свои волосы на этом в течение нескольких дней. Я не могу понять, что происходит. Я разрабатываю WebApp с использованием GWT, который взаимодействует с другим сервером, используя RestAPI. Я использую клиент Джерси для связи с сервером, отличным от серверной части проекта GWT.

По сути, у меня проблемы с анализом Джексона JSON, возвращенного с сервера RestAPI. Объекты JSON, которые он анализирует, успешно используются в приложениях Android, а также в приложениях IOS без проблем с сервером RestAPI.

По сути, чтобы отладить проблему, я вынул медиа-плагин Джерси и попросил Джерси просто вернуть строку объекта, а затем передать строку в ObjectMapper. Я использую последнюю версию Джексона 2.4.4.

У меня есть специальный десериализатор, который работает с форматом даты, и ошибки, которые я получаю, всегда связаны с этой датой. Необработанный JSON выглядит хорошо, но средство сопоставления объектов Джексона выдает ошибку. Ошибка не всегда в одной и той же позиции, но всегда с 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)

Сумасшедший, иногда он работает без ошибок, иногда нет....

Любая помощь, будет оценена....

1 ответ

Решение

Я понял! Я обнаружил, что 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);
        }

    }
}
Другие вопросы по тегам