json - Spring Boot - RESTful Controller 、hateoas 和 JSON

标签 json spring-mvc spring-boot spring-hateoas

所以我浏览了一些关于使用 spring hateoas(带 spring-boot)的文档和示例。因此,通过以下示例,我创建了 2 个 Controller 。

这是第一个片段:

@RestController
@RequestMapping(value = "/users", produces = MediaType.APPLICATION_JSON_VALUE)
public class UserController {
    @Autowired
    private UserService userService;

    @RequestMapping(method = RequestMethod.GET)
    public HttpEntity<Resources<Resource<UserResponse>>> findAll() {
        List<UserResponse> userList = userService.finaAll();

        List<Resource<UserResponse>> resources = Lists.newArrayList();
        for (UserResponse user : userList) {
            Resource<UserResponse> userResource = new Resource<UserResponse>(user);
            resources.add(userResource);
            userResource.add(linkTo(methodOn(UserController.class).findAll()).withSelfRel());
            userResource.add(linkTo(methodOn(UserController.class).findById(user.getId())).withRel("viewUser"));
        }

        return new ResponseEntity(new Resources(resources), HttpStatus.OK);
    }
}

这是 UserResponse DTO:

public class UserResponse {

    private Long id;

    private String firstName;

    private String lastName;

    private String socialNumber;

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate dateOfBirth;
}

为简洁起见,删除了 getter 和 setter,唯一值得一提的是 ID 属性的 getter/setter 上有 @JsonIgnore 和 @JsonProperty。

现在我得到的响应如下:

{
  "_embedded" : {
    "userResponses" : [ {
      "firstName" : "Brand",
      "lastName" : "White",
      "socialNumber" : "342asd3423",
      "dateOfBirth" : "1987-04-04",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users"
        },
        "viewUser" : {
          "href" : "http://localhost:8080/users/10"
        }
      }
    }, {
      "firstName" : "Snow",
      "lastName" : "Green",
      "socialNumber" : "3423cxvx423",
      "dateOfBirth" : "1987-01-12",
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/users"
        },
        "viewUser" : {
          "href" : "http://localhost:8080/users/11"
        }
      }
    } ]
  }
}

问题一:根据http://docs.spring.io/spring-hateoas/docs/current/reference/html/格式应该是这样的:

links : [ { rel : "self", href : "http://myhost/people" } ] } in my example it looks like like "rel" is an attribute.

我有第二个 Controller ,基本上是复制粘贴的:

@RestController
@RequestMapping(value = "/users/{userId}/details", produces = MediaType.APPLICATION_JSON_VALUE)
public class DetailsController {
    //... services ...
    @RequestMapping(method = RequestMethod.GET)
    public HttpEntity<Resources<Resource<DetailsResponse>>> findAllUserDetails(@PathVariable("userId") Long userId) {
        Iterable<UserDetails> details = userDetails.findAll();

        List<Resource<DetailsResponse>> hyperList = Lists.newArrayList();

        for (UserDetails detail : details) {
            Resource<DetailsResponse> hyperRes = new Resource<DetailsResponse>(new DetailsResponse(details));
            hyperRes.add(linkTo(DetailsController.class, userId).withSelfRel());
            hyperRes.add(linkTo(DetailsController.class, userId).slash("/" + detail.getId()).withRel("viewDetail"));
            hyperRes.add(linkTo(DetailsController.class, userId).slash("/" + detail.getId()).withRel("updateDetail"));

            hyperList.add(hyperRes);
        }

        return new ResponseEntity(hyperList, HttpStatus.OK);
    }
}

这个单一的方法产生这样的响应:

{
    "lifespanDays": 60,
    "status": "deceased",
    "dateBorn": [
        2015,
        4,
        5
    ],
    "dateDied": [
        2015,
        6,
        4
    ],
    "links": [
        {
        "rel": "self",
        "href": "http://localhost:8080/users/10/details"
        },
        {
        "rel": "viewDetail",
        "href": "http://localhost:8080/users/10/details/30"
        },
        {
        "rel": "updateDetail",
        "href": "http://localhost:8080/users/10/details/30"
        }
    ]
}

第二个 Controller 的 DTO:

public class UserDetailResponse {

    private Long lifespanDays;

    private String status;

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate dateBorn;

    @JsonDeserialize(using = LocalDateDeserializer.class)
    @JsonSerialize(using = LocalDateSerializer.class)
    @DateTimeFormat(iso = DateTimeFormat.ISO.DATE)
    private LocalDate dateDied;
}

我不明白哪种格式适合 JSON?而且我也不明白为什么它们会有所不同,尽管在类型上指定的 produces MediaType 都是 application/json 。此外,UserDetail 响应中的日期格式也已更改....

两个 Controller 都在同一个包下,都有相同的注释。这是开箱即用的 Spring-Boot,带有一堆 stater 依赖项:

compile('org.springframework.boot:spring-boot-starter-web:1.2.2.RELEASE')
compile('org.springframework.hateoas:spring-hateoas:0.17.0.RELEASE')
compile('org.springframework.boot:spring-boot-starter-data-rest:1.2.2.RELEASE') { transitive = true; }
compile('com.google.code.gson:gson:2.3.1');
compile('org.springframework.boot:spring-boot-starter-data-jpa:1.2.2.RELEASE') { transitive = true; };
compile('com.google.guava:guava:18.0')
compile('commons-beanutils:commons-beanutils:1.9.2')
runtime('org.hsqldb:hsqldb:2.3.2');

最佳答案

问题一:

Spring Boot 中默认的响应格式是 HAL ,这就是你得到的。链接的序列化确实与您预期的不同。 Spring HATEOAS 为负责此操作的 Jackson 注册了一个模块。顺便说一句:文档没有明确说明链接的呈现。

问题二:

由 OP 在评论中回答。

FWIW:两个响应都是正确的 JSON。

关于json - Spring Boot - RESTful Controller 、hateoas 和 JSON,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29459625/

相关文章:

php - echo json_encode 响应不适用于邮件功能

json - 在使用 serde_json 解析时是否可以展平子对象字段?

java - Spring Security 无效登录处理

spring - 使用特定的 application.properties 文件将 Spring Boot 应用程序部署到 Heroku

ios - Swift:由于 URLSession.DataTask 递归调用 ViewDidLoad

java - 如何使用以编程方式创建的父上下文在嵌入式 Servlet 3 环境中创建基于 Spring(4) XML 的 WebApplicationContext?

java - Tomcat,Spring MVC,在不使用 htaccess 文件的情况下将用户重定向到 'www'

java - 未调用 Spring Boot RequestMapping 方法

java - Spring Boot Rest api - 我可以在不为响应对象创建任何 java 类(DTO 或实体)的情况下获得响应吗?

java - 如何循环 JSON 并将其转换为 Java 对象