使用spring-hateoas反序列化包含(_links和_embedded)的JSON

Hey*_*ojo 12 java spring json jackson spring-hateoas

我试图invoque非常简单的json webservices返回此表单的数据:

{
    "_embedded": {
        "users": [{
            "identifier": "1",
            "firstName": "John",
            "lastName": "Doe",
            "_links": {
                "self": {
                    "href": "http://localhost:8080/test/users/1"
                }
            }
        },
        {
            "identifier": "2",
            "firstName": "Paul",
            "lastName": "Smith",
            "_links": {
                "self": {
                    "href": "http://localhost:8080/test/users/2"
                }
            }
        }]
    },
    "_links": {
     "self": {
       "href": "http://localhost:8080/test/users"
     }
   },
   "page": {
     "size": 20,
     "totalElements": 2,
     "totalPages": 1,
     "number": 0
   }
}
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它非常直接.解析链接没有问题,我的POJO从ResourceSupport扩展.这是他们的样子:

UsersJson(根元素)

public class UsersJson extends ResourceSupport {
    private List<UserJson> users;

    [... getters and setters ...]
}
Run Code Online (Sandbox Code Playgroud)

UserJson

public class UserJson extends ResourceSupport {

    private Long identifier;

    private String firstName;

    private String lastName;

    [... getters and setters ...]
}
Run Code Online (Sandbox Code Playgroud)

问题是我期待jackson和spring足够智能来解析_embedded属性并填充我的UsersJson.users属性,但事实并非如此.

我尝试了在互联网上找到的各种各样的东西,但我唯一可以正常工作的是创建一个充当_embedded包装器的新类:

UsersJson(根元素)

public class UsersJson extends ResourceSupport {
    @JsonProperty("_embedded")
    private UsersEmbeddedListJson  embedded;

    [... getters and setters ...]
}
Run Code Online (Sandbox Code Playgroud)

嵌入式"包装"

public class UsersEmbeddedListJson extends ResourceSupport {
    private List<UserJson> users;

    [... getters and setters ...]
}
Run Code Online (Sandbox Code Playgroud)

它有效,但我发现它很难看.

然而,我虽然RestTemplate的以下配置会起作用(特别是当我在Jackson2HalModule中看到EmbeddedMapper时),但它没有:

        ObjectMapper mapper = new ObjectMapper();
        mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        mapper.registerModule(new Jackson2HalModule());

        MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
        converter.setSupportedMediaTypes(MediaType.parseMediaTypes("application/hal+json"));
        converter.setObjectMapper(mapper);

        RestTemplate restTemplate = new RestTemplate(Collections.singletonList(converter));

        ResponseEntity<UsersJson> result = restTemplate.getForEntity("http://localhost:8089/test/users", UsersJson.class, new HashMap<String, Object>());
        System.out.println(result);
Run Code Online (Sandbox Code Playgroud)

有人能告诉我我错过了什么吗?

Hey*_*ojo 10

最后,我找到了一种更好的方式来使用那些 application/hal+json API。

Spring hateoas 实际上提供了一个几乎可以使用的客户端:org.springframework.hateoas.client.Traverson。

Traverson traverson = new Traverson(new URI("http://localhost:8080/test"), MediaTypes.HAL_JSON);
TraversalBuilder tb = traverson.follow("users");
ParameterizedTypeReference<Resources<UserJson>> typeRefDevices = new ParameterizedTypeReference<Resources<UserJson>>() {};
Resources<UserJson> resUsers = tb.toObject(typeRefDevices);
Collection<UserJson> users= resUsers .getContent();
Run Code Online (Sandbox Code Playgroud)

如您所见,我摆脱了 UsersJson 和 UsersEmbeddedListJson。

这是我添加的 maven 依赖项

    <dependency>
        <groupId>org.springframework.hateoas</groupId>
        <artifactId>spring-hateoas</artifactId>
        <version>0.19.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.plugin</groupId>
        <artifactId>spring-plugin-core</artifactId>
        <version>1.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.jayway.jsonpath</groupId>
        <artifactId>json-path</artifactId>
        <version>2.0.0</version>
    </dependency>
Run Code Online (Sandbox Code Playgroud)

  • 我和你面临同样的问题。当我尝试您使用 `restTemplate.follow("users")` 的建议时,我收到一个错误,如“预期找到与 rel 'users' 作为响应的链接”。在某种意义上,这个错误是有道理的,因为我认为“follow”api 期望它指向某个 URL,但在这种情况下它不是。不确定我是否在这里做错了什么 (4认同)

Whi*_*cal 5

必须将其添加到我的 DTO 中:

@JsonProperty("_links")
public void setLinks(final Map<String, Link> links) {
    links.forEach((label, link) ->  add(link.withRel(label)) );
}
Run Code Online (Sandbox Code Playgroud)

因为 ResourceSupport 没有用于链接的 POJO 标准/Json 信号设置器/构造函数