Spring Hateoas ControllerLinkBuilder 添加了 null 字段

2022-09-04 20:33:49

我正在学习Spring REST的教程,并尝试将HATEOAS链接添加到我的控制器结果中。

我有一个简单的User类和一个CRUD控制器。

class User {
    private int id;
    private String name;
    private LocalDate birthdate;
    // and getters/setters
}

服务:

@Component
class UserService {
    private static List<User> users = new ArrayList<>();
    List<User> findAll() {
        return Collections.unmodifiableList(users);
    }
    public Optional<User> findById(int id) {
        return users.stream().filter(u -> u.getId() == id).findFirst();
    }
    // and add and delete methods of course, but not important here
}

一切正常,除了在我的控制器中,我想添加从所有用户列表到单个用户的链接:

import static org.springframework.hateoas.mvc.ControllerLinkBuilder.linkTo;
import static org.springframework.hateoas.mvc.ControllerLinkBuilder.methodOn;

@RestController
public class UserController {
    @Autowired
    private UserService userService;
    @GetMapping("/users")
    public List<Resource<User>> getAllUsers() {
        List<Resource<User>> userResources = userService.findAll().stream()
            .map(u -> new Resource<>(u, linkToSingleUser(u)))
            .collect(Collectors.toList());
        return userResources;
    }
    Link linkToSingleUser(User user) {
        return linkTo(methodOn(UserController.class)
                      .getById(user.getId()))
                      .withSelfRel();
    }

以便为结果列表中的每个用户添加指向用户本身的链接。

链接本身创建得很好,但是在生成的 JSON 中存在多余的条目:

[
    {
        "id": 1,
        "name": "Adam",
        "birthdate": "2018-04-02",
        "links": [
            {
                "rel": "self",
                "href": "http://localhost:8080/users/1",
                "hreflang": null,
                "media": null,
                "title": null,
                "type": null,
                "deprecation": null
            }
        ]
    }
]

具有空值(等)的字段来自哪里,为什么添加它们?有没有办法摆脱它们?hreflangmedia

在构建指向“所有用户”列表的链接时,它们不会显示:

@GetMapping("/users/{id}")
public Resource<User> getById(@PathVariable("id") int id) {
    final User user = userService.findById(id)
                                 .orElseThrow(() -> new UserNotFoundException(id));
    Link linkToAll = linkTo(methodOn(UserController.class)
                            .getAllUsers())
                            .withRel("all-users");
    return new Resource<User>(user, linkToAll);
}

答案 1

为了进一步参考,以防其他人偶然发现这一点,我想通了:我添加了一个条目,即application.properties

spring.jackson.default-property-inclusion=NON_NULL

为什么这对对象是必要的,但对于我不知道的不是(也没有深入的划分)。LinkUser


答案 2

正如 semiintel 所提到的,问题在于 List 返回对象不是有效的 HAL 类型:

public List<Resource<User>> getAllUsers()

这可以通过将返回类型更改为资源来轻松解决,如下所示:

public Resources<Resource<User>> getAllUsers()

然后,只需将资源<>列表包装在资源<>对象中,方法是将 return 语句从以下位置更改:

return userResources;

自:

return new Resources<>(userResources)

然后,您应该获得正确的链接序列化,就像对单个对象所做的那样。

此方法由这篇非常有用的文章提供,用于解决此问题:

https://www.logicbig.com/tutorials/spring-framework/spring-hateoas/multiple-link-relations.html


推荐