【问题标题】:Spring Data REST: "no String-argument constructor/factory method to deserialize from String value"Spring Data REST:“没有从字符串值反序列化的字符串参数构造函数/工厂方法”
【发布时间】:2017-04-20 13:59:32
【问题描述】:

当我在 Spring Data REST 应用程序中使用 Lombok 来定义复杂类型时:

@NoArgsConstructor
@AllArgsConstructor
@Data

@Entity
@Table(name = "BOOK")
public class Book {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(nullable = false)
    private Long id;

    private String title;

    @ManyToOne(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.REFRESH})
    private Person author;

    // ...
}

使用 Spring Data REST 控制器,例如:

@RepositoryRestController
public class BookRepositoryRestController {

    private final BookRepository repository;

    @Autowired
    public BookRepositoryRestController(BookRepository repository) {
        this.repository = repository;
    }

    @RequestMapping(method = RequestMethod.POST,value = "/books")
    public @ResponseBody PersistentEntityResource post(
        @RequestBody Book book,
        PersistentEntityResourceAssembler assembler) {

        Book entity = processPost(book);

        return assembler.toResource(entity);
    }

    private Book processPost(Book book) {
        // ...
        return this.repository.save(book);
    }
}

我收到一个丑陋的错误:

no String-argument constructor/factory method to deserialize from String value

来自 Spring Data REST 对 Jackson 的使用与 Book POST 类似:

curl -X POST 
     -H 'content-type: application/json' 
     -d '{"title":"Skip Like a Pro", "author": "/people/123"}'
     http://localhost:8080/api/books/

当 Jackson 尝试解析应解析为单个唯一的 Person 的本地 URI /people/123 时,会发生反序列化错误。如果我删除我的@RepositoryRestController,一切正常。知道我的 REST 控制器定义有什么问题吗?

【问题讨论】:

  • 嗨 Jan,你为什么在 AllArgsConstructor 中使用 suppressConstructorProperties = true ? Lombok dosumentation 说:'如果设置为 true,则 lombok 将跳过将 @java.beans.ConstructorProperties 添加到生成的构造函数。这在注释通常不可用的 android 和 GWT 开发中很有用。看来您不属于推荐的情况。如果删除此配置会怎样?
  • 请检查 Lombok 中的 @Data 注释。它生成等号和哈希码。
  • @avi613 -- 不幸的是,Jackson 的反序列化在没有@AllArgsConstructor(suppressConstructorProperties = true) 的情况下触发了上述错误 -- 这可能是 Lombok 错误。

标签: java spring java-8 spring-data-rest lombok


【解决方案1】:

@RepositoryRestController 中,将@RequestBody 参数的类型从Book 更改为Resource<Book>

import org.springframework.hateoas.Resource;

    // ...

    @RequestMapping(method = RequestMethod.POST,value = "/books")
    public @ResponseBody PersistentEntityResource post(
        @RequestBody Resource<Book> bookResource,             // Resource<Book>
        PersistentEntityResourceAssembler assembler) {

        Book book = bookResource.getContent()
        // ...
    }

并在Book 实体定义中将AllArgsConstructor 注释修改为:@AllArgsConstructor(suppressConstructorProperties = true)

更多信息请参见Spring Data REST #687

【讨论】:

  • 我正在使用 @RepositoryRestResource 公开我的存储库(作为 spring-data-rest HATEOAS 资源)我没有任何 RepositoryRestController。但我得到同样的错误。我该如何解决?
  • @Robert - 这可能是相同的基本问题:Jackson 无法反序列化您的数据;但是,对于您的情况,解决方案会有所不同。我建议您打开一个包含所有详细信息的新问题...
  • @Robert 你在使用 \@RepositoryRestResource 时有没有找到解决方案?
猜你喜欢
  • 2017-12-23
  • 2017-03-03
  • 2018-09-09
  • 1970-01-01
  • 2019-12-31
  • 2021-09-22
  • 1970-01-01
  • 2019-05-15
  • 2019-06-14
相关资源
最近更新 更多