Spring Batch: JSON неправильно преобразован в список<SampleItem>

В моей работе Spring Batch первым шагом является чтение данных JSON из службы REST и запись их в локальную таблицу HSQL для последующей обработки.

Мой звонок RestTemplate.exchange() действительно получает ожидаемый JSON, и он конвертирует JSON в List<SampleItem>,

Тем не менее, как ни странно, на SampleItem объекты в списке. Это как если бы MappingJackson2HttpMessageConverter не находит свойства бобов?

Определение должности:

  <batch:job id="samples_results.job" restartable="false">
      <batch:step id="get.samples" next="get.results">
          <batch:tasklet>
              <!-- 1. HERDS survey data about outlet samples so far. Form #1  -->
              <batch:chunk reader="samples.rest.item.reader" writer="samples.hsqldb.item.writer" commit-interval="${commit.interval}"/>
          </batch:tasklet>
      </batch:step> 
      ...
      <batch:listeners>
          <batch:listener ref="job.listener"/>
      </batch:listeners>
      <batch:validator ref="job.parameters.validator"/>
  </batch:job>

  <beans:bean id="samples.rest.item.reader" class="gov.ny.health.adsg.ceh.slrs_hdny.SamplesRestItemReader">
    <beans:property name="activityId" value="${samples.activity.id}"/>
    <beans:property name="formId" value="${samples.form.id}"/>
    <beans:property name="username" value="${herds.uname}"/>
    <beans:property name="password" value="${herds.password}"/>
  </beans:bean>

  <beans:bean id="samples.hsqldb.item.writer" class="org.springframework.batch.item.database.JdbcBatchItemWriter">
    <beans:property name="dataSource" ref="dataSource" />
    <beans:property name="sql">
      <beans:value><![CDATA[insert into t_sample(org_id, name, address) values (:ORG_ID, :ORG_NAME, :ADDRESS_1)]]></beans:value>
    </beans:property>
    <beans:property name="itemSqlParameterSourceProvider">
      <beans:bean class="org.springframework.batch.item.database.BeanPropertyItemSqlParameterSourceProvider" />
    </beans:property>
  </beans:bean>

Соответствующий ItemReader код, который успешно возвращает List<SampleItem> с одним элементом (но без атрибутов для этого элемента):

try {
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.set("Accept", MediaType.APPLICATION_JSON_VALUE);
    headers.set("Authorization", this.getBasicAuthString_());
    HttpEntity<String> requestEntity = new HttpEntity<String>(headers);
    ParameterizedTypeReference<List<SampleItem>> typeRef = new ParameterizedTypeReference<List<SampleItem>>(){};
    ResponseEntity<List<SampleItem>> response = restTemplate.exchange(URL, HttpMethod.GET, requestEntity, typeRef, this.activityId, this.formId);
    this.list = response.getBody(); if (isDebug) {buf.append(NL).append("list.size=").append(null!=this.list ? this.list.size() : -1).append(NL).append("list[0]=").append(null!=this.list && !this.list.isEmpty() ? this.list.get(0).toString() : "null");}
    this.iterator = null!=this.list ? this.list.iterator() : null;
} catch (Exception e) {
    logger.error(e.getMessage());
    throw e;
} finally {
    if (isDebug) {
        logger.debug(buf.toString());
    }
}

SampleItem боб. Обратите внимание на атрибуты верхнего регистра, пытаясь сопоставить JSON:

@JsonIgnoreProperties(ignoreUnknown = true)
public class SampleItem implements Serializable {

    public String getORG_NAME() {
        return ORG_NAME;
    }

    public void setORG_NAME(String s) {
        this.ORG_NAME = s;
    }

    public String getADDRESS_1() {
        return ADDRESS_1;
    }

    public void setADDRESS_1(String s) {
        this.ADDRESS_1 = s;
    }

    public String getORG_ID() {
        return ORG_ID;      
    }

    public void setORG_ID(String s) {
        this.ORG_ID = s;
    }

    public String toString() {
        StringBuilder buf = new StringBuilder(getClass().getName());
        buf.append("{").append(this.ORG_ID).append("}");
        return buf.toString();
    }

    public int hashCode() {
        return this.toString().hashCode();
    }

    public boolean equals(Object other) {
        boolean b = null!=other && (other instanceof SampleItem);
        if (b) {
            b = this.toString().equals(other.toString());
        }
        return b;
    }

    private String ACT_ID = null;
    private String ORG_ID = null;
    private String ORG_NAME = null;
    private String ADDRESS_1 = null;

    private static final long serialVersionUID = -4839970923454745745L;

}

Вернул JSON. Все атрибуты уведомлений в верхнем регистре:

2016-09-15 14:14:29 [main] DEBUG g.n.h.a.c.s.SamplesRestItemReader pJsonString_ - json.str: [{"ACT_ID":7704,"ADDRESS_1":"800 North Pearl Street","ADDRESS_2":null,"DATAENTITY_ID":58184,"ENTITY_END_DATE":"06-JUN-2079","ENTITY_TYPE_ID":74,"HERDS_TABLE_NAME":"SCHOOLDRINKING_13536_00","ID1":"888888888889","ID2":"888888880000","LAST_SUBMITTED_DATE":"14/Sep/2016 09:34:11","LAST_SUBMITTED_USER":"tmb03","ORG_ID":58184,"ORG_ID1":"888888888889","ORG_NAME":"Z TEST PUBLIC SCHOOL","ORG_TYPE_ID":74,"POSTAL_CODE":"12204","SCH_LEAD_DT_COMPLETE_61752":"9/14/16","SCH_LEAD_OUTLETS_POSTR_61749":20,"SCH_LEAD_PREREG_COMPLI_61769":50,"SCH_LEAD_PREREG_NONCOM_61770":30,"SCH_LEAD_RESULTS_WEBSI_61927":null,"SCH_LEAD_SAMPLING_ATTE_61750":"on","SCH_LEAD_SAMPLING_COMP_61751":"on","SCH_LEAD_TOTAL_OUTLETS_61768":100,"SCH_LEAD_WAIVER_GRANTE_61772":0,"SCH_LEAD_WAIVER_PENDIN_61771":30,"TIME_SERIES_DATE":null,"TOWN_CITY":"Albany"}]

...

Правильные результаты, но ORG_ID не установлен:

2016-09-15 14:14:30 [main] DEBUG g.n.h.a.c.s.SamplesRestItemReader init_ - 
    URL=https://sgw.health.state.ny.us/doh2/applinks/webserv/herdsrestfulservices/surveyData/allfieldsdata/{activityId}/{formId}
    activity=7704
    form=13536
    list.size=1
    list[0]=gov.ny.health.adsg.ceh.slrs_hdny.SampleItem{null}
...

Я пробовал каждую комбинацию атрибутов верхнего и нижнего регистра SampleItem боб.

Любые предложения приветствуются.

1 ответ

Я подозреваю, что вы сталкиваетесь со стратегией именования свойств по умолчанию, предложенной Джексоном в нижнем регистре с некоторыми именами свойств, с https://fasterxml.github.io/jackson-databind/javadoc/2.2.0/com/fasterxml/jackson/databind/PropertyNamingStrategy.html:

В отсутствие зарегистрированной пользовательской стратегии используется стратегия именования свойств Java по умолчанию, которая оставляет имена полей как есть и удаляет префикс set / get / is из методов (а также начальную последовательность строчных букв в нижнем регистре)

Я не могу найти более конкретную спецификацию алгоритма нижнего регистра, но вместо того, чтобы пытаться угадать его, просто явно назовите свойство, например:

@JsonProperty("ACT_ID")
private String ACT_ID = null;

Вы составляете вещи, указывая @JsonIgnoreProperties(ignoreUnknown = true) - если вы удалите это, вы можете получить полезное исключение при десериализации, а не пустой объект.

Стоит написать простой модульный тест для сериализации json (de), чтобы определить эти проблемы.

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