6

Spring をサポートする RESTful Web サービスを構築しようとしています。POST リクエストを送信しようとすると、次の例外が発生します。

入力:

POST    http://localhost:8080/InventoryDemo/item

JSON ペイロード:

{"materialId":"ID02","materialName":"Material_2","materialCategory":"LIQUID","currency":"RUPEES","unitCostInCurrency":2200.0,"quantityLevel":1000,"quantityAtDate":"2016-04-11","warehouseName":"WareHouse_2"}

例外:

WARNING: Handler execution resulted in exception: Could not read document: Can not instantiate value of type [simple type, class java.time.LocalDate] from String value ('2016-04-11'); no single-String constructor/factory method
 at [Source: java.io.PushbackInputStream@378ace07; line: 1, column: 146] (through reference chain: com.psl.inventory.model.InventorySystemModel["quantityAtDate"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class java.time.LocalDate] from String value ('2016-04-11'); no single-String constructor/factory method
 at [Source: java.io.PushbackInputStream@378ace07; line: 1, column: 146] (through reference chain: com.psl.inventory.model.InventorySystemModel["quantityAtDate"])

これは @RestController からの私の POST メソッドです:

@RequestMapping(value = "/item", method = RequestMethod.POST)
    public ResponseEntity<Void> createInventorySystemModel(@RequestBody InventorySystemModel inventorySystemModel,  UriComponentsBuilder ucBuilder) {
        System.out.println("Creating InventorySystemModel " + inventorySystemModel.getMaterialName());

        if (inventorySystemService.isInventorySystemModelExist(inventorySystemModel)) {
            System.out.println("A InventorySystemModel with name " + inventorySystemModel.getMaterialName() + " already exist");
            return new ResponseEntity<Void>(HttpStatus.CONFLICT);
        }

        inventorySystemService.saveInventoryItem(inventorySystemModel);

        HttpHeaders headers = new HttpHeaders();
        headers.setLocation(ucBuilder.path("/user/{materialId}").buildAndExpand(inventorySystemModel.getMaterialId()).toUri());
        return new ResponseEntity<Void>(headers, HttpStatus.CREATED);
    }

これは私のPOJOクラスです:

public class InventorySystemModel {

    private String materialId;
    private String materialName;
    private String materialCategory;
    private String currency;
    private double unitCostInCurrency;
    private int quantityLevel;
    private LocalDate quantityAtDate;
    private String warehouseName;

    public InventorySystemModel(){

    }
    public InventorySystemModel(String materialId, String materialName,
            String materialCategory, String currency,
            double unitCostInCurrency, int quantityLevel, LocalDate quantityAtDate,
            String warehouseName) {
        super();
        this.materialId = materialId;
        this.materialName = materialName;
        this.materialCategory = materialCategory;
        this.currency = currency;
        this.unitCostInCurrency = unitCostInCurrency;
        this.quantityLevel = quantityLevel;
        this.quantityAtDate = quantityAtDate;
        this.warehouseName = warehouseName;
    }

    public String getMaterialId() {
        return materialId;
    }
    public void setMaterialId(String materialId) {
        this.materialId = materialId;
    }
    public String getMaterialName() {
        return materialName;
    }
    public void setMaterialName(String materialName) {
        this.materialName = materialName;
    }
    public String getMaterialCategory() {
        return materialCategory;
    }
    public void setMaterialCategory(String materialCategory) {
        this.materialCategory = materialCategory;
    }
    public String getCurrency() {
        return currency;
    }
    public void setCurrency(String currency) {
        this.currency = currency;
    }
    public double getUnitCostInCurrency() {
        return unitCostInCurrency;
    }
    public void setUnitCostInCurrency(double unitCostInCurrency) {
        this.unitCostInCurrency = unitCostInCurrency;
    }
    public int getQuantityLevel() {
        return quantityLevel;
    }
    public void setQuantityLevel(int quantityLevel) {
        this.quantityLevel = quantityLevel;
    }
    public LocalDate getQuantityAtDate() {
        return quantityAtDate;
    }
    public void setQuantityAtDate(LocalDate quantityAtDate) {
        this.quantityAtDate = quantityAtDate;
    }
    public String getWarehouseName() {
        return warehouseName;
    }
    public void setWarehouseName(String warehouseName) {
        this.warehouseName = warehouseName;
    }
    @Override
    public int hashCode() {
        final int prime = 31;
        int result = 1;
        result = prime * result
                + ((currency == null) ? 0 : currency.hashCode());
        result = prime
                * result
                + ((materialCategory == null) ? 0 : materialCategory.hashCode());
        result = prime * result
                + ((materialId == null) ? 0 : materialId.hashCode());
        result = prime * result
                + ((materialName == null) ? 0 : materialName.hashCode());
        result = prime * result
                + ((quantityAtDate == null) ? 0 : quantityAtDate.hashCode());
        result = prime * result + quantityLevel;
        long temp;
        temp = Double.doubleToLongBits(unitCostInCurrency);
        result = prime * result + (int) (temp ^ (temp >>> 32));
        result = prime * result
                + ((warehouseName == null) ? 0 : warehouseName.hashCode());
        return result;
    }
    @Override
    public boolean equals(Object obj) {
        if (this == obj)
            return true;
        if (obj == null)
            return false;
        if (getClass() != obj.getClass())
            return false;
        InventorySystemModel other = (InventorySystemModel) obj;
        if (currency == null) {
            if (other.currency != null)
                return false;
        } else if (!currency.equals(other.currency))
            return false;
        if (materialCategory == null) {
            if (other.materialCategory != null)
                return false;
        } else if (!materialCategory.equals(other.materialCategory))
            return false;
        if (materialId == null) {
            if (other.materialId != null)
                return false;
        } else if (!materialId.equals(other.materialId))
            return false;
        if (materialName == null) {
            if (other.materialName != null)
                return false;
        } else if (!materialName.equals(other.materialName))
            return false;
        if (quantityAtDate == null) {
            if (other.quantityAtDate != null)
                return false;
        } else if (!quantityAtDate.equals(other.quantityAtDate))
            return false;
        if (quantityLevel != other.quantityLevel)
            return false;
        if (Double.doubleToLongBits(unitCostInCurrency) != Double
                .doubleToLongBits(other.unitCostInCurrency))
            return false;
        if (warehouseName == null) {
            if (other.warehouseName != null)
                return false;
        } else if (!warehouseName.equals(other.warehouseName))
            return false;
        return true;
    }
    @Override
    public String toString() {
        return "InventorySystemModel [materialId=" + materialId
                + ", materialName=" + materialName + ", materialCategory="
                + materialCategory + ", currency=" + currency
                + ", unitCostInCurrency=" + unitCostInCurrency
                + ", quantityLevel=" + quantityLevel + ", quantityAtDate="
                + quantityAtDate + ", warehouseName=" + warehouseName + "]";
    }
}

参考までに:この投稿を確認しましたが、正確にどこを変更する必要があるかについての手がかりが得られませんでした。

Java 8 と Spring 4.2 を使用しています

ここで正確に何をする必要があるかなど、詳細に説明してください。 また、GETリクエストをヒットするときに同じ日付形式が必要です。

ありがとう。

4

4 に答える 4

7

カスタムLocalDate デシリアライザーを作成できます。このデシリアライザーは、 LocalDate変数のセッター メソッドが呼び出されたときに呼び出されます。

手順は次のとおりです。

  1. カスタム デシリアライザーを定義する

    public class LocalDateDeserializer extends JsonDeserializer<LocalDate>{
    
      @Override
      public LocalDate deserialize(JsonParser p, DeserializationContext ctxt)
            throws IOException, JsonProcessingException {
    
          DateTimeFormatter formatter = DateTimeFormatter.ofPattern("required format");
    
          LocalDate localDate = null;
          localDate = LocalDate.parse(p.getText(), formatter);
    
          return localDate;
      }
    }
    

注: LocalDate.parseメソッドの参照。

  1. 変数の上に @JsonDeserialize アノテーションを定義する

    @JsonDeserialize(using=LocalDateDeserializer.class)
    private LocalDate quantityAtDate;
    

@JsonDeserialize アノテーションのインポートを使用するには、次のようにします。

com.fasterxml.jackson.databind.annotation.JsonDeserialize をインポートします。

お役に立てれば。

于 2017-08-14T07:13:26.567 に答える
5

エラー

JsonMappingExceptionJava の JSON パーサーである Jackson によってスローされる例外です。これは、JSON を Java Bean にマッピングする際の致命的な問題を示しています。

この状況では、Java 8 から文字列2016-04-11を解析できないようです。LocalDate

修正方法

Jackson は Java 8 の日付型をサポートしていますが、次の依存関係が必要です。

<dependency>
    <groupId>com.fasterxml.jackson.datatype</groupId>
    <artifactId>jackson-datatype-jsr310</artifactId>
    <version>${jackson.version}</version>
</dependency>

そして、次のように構成しますObjectMapper

@Configuration
public class JacksonConfig {

    @Bean
    public ObjectMapper createObjectMapper() {  
        ObjectMapper mapper = new ObjectMapper();
        mapper.registerModule(new JavaTimeModule());
        mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        return mapper;
    }
}

デフォルトでは、日付はISO 8601形式でシリアル化されます。フォーマットを変更したい場合は、次を使用できます@JsonFormat

@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM")
private LocalDate date;

カスタム (デ) シリアライザーは必要ありません。

于 2017-08-14T07:34:22.020 に答える