【问题标题】:ResponseEntity not parsing certain boolean and string values from JSON (Inconsistently)ResponseEntity 未从 JSON 解析某些布尔值和字符串值(不一致)
【发布时间】:2021-06-21 10:42:26
【问题描述】:

不确定我是不是发疯了,但我设置了一个非常简单的 POST 映射来接收数据类型为字符串和布尔值的 JSON 响应。由于某种原因,该方法正在更改我的字段名称,并且它也无法解析 2 个布尔变量和 一些 字符串变量的值。

注意事项:

  1. 我在同一个项目中的另一个实体/控制器/存储库(访问者类)中使用布尔和字符串/数字数据类型进行了测试,它可以正常工作。
  2. 提交到数据库的数据已经是错误的(因此返回响应是错误的),所以我认为最初解析来自 ResponseEntity 的数据是问题所在。
  3. 我尝试在我的表架构中同时使用 BIT 和 BOOLEAN,但两者结果相同。

提前感谢您的任何反馈!

实体

    package com.vmsac.vmsacserver.model;

    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;

    import javax.persistence.*;

    @NoArgsConstructor
    @AllArgsConstructor
    @Entity
    @Data
    @Table(name="scheduledvisit")
    public class ScheduledVisit {

    @Id
    @GeneratedValue (strategy = GenerationType.IDENTITY)
    @Column(name="scheduledvisitid")
    private Long scheduledVisitId;
    @Column(name="visitorid")
    private Long visitorId;
    @Column(name="startdateofvisit")
    private String startDateofVisit;
    @Column(name="enddateofvisit")
    private String endDateofVisit;
    @Column(name="qrcodeid")
    private Long qrCodeId;
    @Column(name="isvalid")
    private boolean isValid;
    @Column(name="isonetimeuse")
    private boolean isOneTimeUse;
    @Column(name="raisedby")
    private Long raisedBy;
    }

控制器

package com.vmsac.vmsacserver.controller;
import com.vmsac.vmsacserver.model.ScheduledVisit;
import com.vmsac.vmsacserver.repository.ScheduledVisitRepository;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import javax.validation.Valid;
import java.util.List;
import java.net.URI;
import java.net.URISyntaxException;

@RestController
@RequestMapping("/api")
public class ScheduledVisitController{

    @Autowired
    private ScheduledVisitRepository scheduledVisitRepository;

    @GetMapping(path = "/scheduled-visits")
    List<ScheduledVisit> getScheduledVisits(){
        return scheduledVisitRepository.findAll();
    }

    @PostMapping(path = "/register-scheduled-visit", consumes = "application/json")
    ResponseEntity<ScheduledVisit> createScheduledVisit(@Valid @RequestBody ScheduledVisit scheduledVisit) throws URISyntaxException{
        ScheduledVisit registeredVisit = scheduledVisitRepository.save(scheduledVisit);
        return ResponseEntity.created(new URI("/api/register-scheduled-visit" + registeredVisit.getScheduledVisitId())).body(registeredVisit);

    }

}

存储库

package com.vmsac.vmsacserver.repository;

import com.vmsac.vmsacserver.model.ScheduledVisit;
import org.springframework.data.jpa.repository.JpaRepository;

import java.util.List;

public interface ScheduledVisitRepository extends JpaRepository<ScheduledVisit, Long> {

    List<ScheduledVisit> findByScheduledVisitId(String scheduledVisitId);
}

JSON 对象(使用 Postman)

{
  "visitorId" : 456879,
  "startDateOfVisit" : "10Jan2021",
  "endDateOfVisit" : "12-Jan-2021",
  "qrCodeId" : 12325,
  "isValid" : true,
  "isOneTimeUse" : false,
  "raisedBy" : 123456
}

回应

{
    "scheduledVisitId": 3,
    "visitorId": 456879,
    "startDateofVisit": null, //this string returns null, should have a value
    "endDateofVisit": null, //this string returns null, should have a value
    "qrCodeId": 12325,
    "raisedBy": 123456,
    "valid": false, //field name should be isValid, value should be true
    "oneTimeUse": false //field name should be isOneTimeUse
}

数据库架构

CREATE TABLE ScheduledVisit (
  scheduledVisitId BIGINT NOT NULL AUTO_INCREMENT,
  visitorId BIGINT,
  startDateOfVisit VARCHAR(128),
  endDateOfVisit VARCHAR(128),
  qrCodeId BIGINT,
  isValid BIT,
  isOneTimeUse BIT,
  raisedBy BIGINT,
  PRIMARY KEY (scheduledVisitId)
);

【问题讨论】:

  • 简单的建议,为了让您的实体更具可读性,您可以在每个语句后添加一个空行,这意味着每个 ; 后的空行。这在阅读时会很清楚,因为相关的字段和注释可以作为一个组来阅读。
  • 我也可以推荐使用 dto 而不是直接暴露你的实体。然后您可以灵活地选择要显示的字段等。如果您使用 dto,另一个有用的注释是 @Jacksonized@Builder 的组合。你需要像 MapStruct 这样的想法来将你的 dto 映射到实体。但请仅将其视为与您的实际问题无关的建议。

标签: java json spring


【解决方案1】:

问题是您在 JSON 中:startDateOfVisitendDateOfVisit 带有大写字母 O,在您的 ScheduledVisit 中带有小写字母 o。因此,getter 和 setter 是用 Lombok 也用小写字母 o 创建的,而 Jackson 没有找到这些属性的 getter/setter,因此它们是空值。 因此,请检查您的所有 json 属性是否有合适的 getter 和 setter。

使用布尔值有点复杂,我认为对于 Lombok 来说,最简单的方法是不使用前缀,所以在 ScheduledVisit 中,我会将字段 isValid 重命名为 valid 并将 isOneTimeUse 重命名为 oneTimeUse

否则,您可以为布尔字段重写 Lombok getter/setter,例如像这样:

    private boolean isValid;

    @JsonProperty("isValid")
    public boolean isValid() {
        return isValid;
    }
    
    public void setValid(boolean isValid) {
        this.isValid = isValid;
    }

【讨论】:

  • 非常感谢!这解决了我的问题。另外,感谢上述所有改进建议。
猜你喜欢
  • 1970-01-01
  • 2014-11-30
  • 2013-08-22
  • 2011-07-10
  • 1970-01-01
  • 2018-04-13
  • 1970-01-01
  • 1970-01-01
  • 2016-08-15
相关资源
最近更新 更多