簡體   English   中英

JSON解析錯誤:處理一對一關系時無法構造“自定義對象”的實例

[英]JSON parse error: Cannot construct instance of 'Custom object' while dealing with one to one relation

我正在使用Java和Spring Boot開發REST API。

有兩個具有一對一關系的實體:

用戶:

@Entity
@Table(name = "users")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class User {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column(name = "first_name", nullable = false)
    private String firstName;

    @Column(name = "last_name", nullable = false)
    private String lastName;

    @Column(name = "email", nullable = false, unique = true)
    private String email;

    @OneToOne(fetch = FetchType.LAZY,
            cascade =  CascadeType.ALL,
            mappedBy = "employee")
    @JsonBackReference
    private Company company;

    // constructors, getters & setters...

和公司:

@Entity
@Table(name = "companies")
@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
public class Company {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    @Column(name = "company_name", nullable = false)
    private String companyName;

    @Column(name = "company_info", nullable = false)
    private String companyInfo;

    @CreationTimestamp
    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "created_at", nullable = false)
    private Date createdAt;

    @OneToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "employee_id", nullable = false)
    @JsonManagedReference
    private User employee;

   // constructors, getters & setters...

我希望能夠通過POST方法創建Companies,所以我已經在CompanyController中創建了一個(我在控制器中忽略了GET方法,因為它們按預期工作):

@RestController
@RequestMapping(value = "/api/v1")
public class CompanyController {

    private static final Logger logger = LoggerFactory.getLogger(CompanyController.class);

    @Autowired
    private CompanyRepository companyRepository;

    @PostMapping(path = "company", produces = "application/JSON")
    public ResponseEntity<?> createCompany(@RequestBody Company company){
        logger.info("Request to save new Company: {}", company);

        Company result = companyRepository.save(company);
        return ResponseEntity.ok().body(result);
    }

當我使用JSON發送請求時, createCompany方法工作正常,如下所示:

{
"companyName" : "Big Client Company 2",
"companyInfo" : "unspecified",
"employee" : {
    "id": 17,
    "firstName": "someName",
    "lastName": "someLastName",
    "email": "someEmail@a.ru"
  }
}

但是,我希望能夠發送不帶 employee字段整體但只有一個id的JSON:

{
"companyName" : "Big Client Company 2",
"companyInfo" : "unspecified",
"employee" : 17
}

當我這樣做時,我得到一個錯誤:

JSON解析錯誤:無法構造model.User實例(盡管至少存在一個Creator):沒有用於從Number值反序列化的int / Int參數構造函數/工廠方法

所以, 問題是有沒有辦法做到這一點不改變公司類“雇員”為String(和擺脫的一對1的關系)?

我試圖找到編寫自定義JSON反序列化器的示例,但沒有找到適合我的示例。

問題是您的用戶具有創建必填字段時必須提供的必填字段( firstNamelastNameemail )。

如果沒有使用現有定義的用戶,則無法創建用戶。

您可以在這些字段上使用nullable = true ,但最終可能會導致要保留在數據庫中的數據不一致。 如果讓這些字段為空,那么我建議采用這種方法。

另外,請注意,混合REST控制器層和存儲庫層通常是一種不好的做法。 您應該通過服務層將這些層分開。

您可以使用自定義反序列化:

public class CompanyDeserializer extends StdDeserializer<Company> { 

@Autowired
private UserRepository userRepository;

public CompanyDeserializer() { 
    this(null); 
} 

public CompanyDeserializer(Class<?> vc) { 
    super(vc); 
}

@Override
public Company deserialize(JsonParser jp, DeserializationContext ctxt) 
  throws IOException, JsonProcessingException {
    JsonNode node = jp.getCodec().readTree(jp);
    Company c = new Company();
    //Set the rest of the attributes.
    Long empId = (Long) ((IntNode) node.get("employee")).numberValue();
    c.setEmployee(userRepository.findById(empId).orElse(null)));
    return c;
}

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM