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

Deserialize JSON containing (_links and _embedded) using spring-hateoas

我正在尝试开发非常简单的json网络服务,这些服务返回以下形式的数据:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
{
   "_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
   }
}

如您所见,它非常简单。
我的POJO扩展了ResourceSupport,因此解析链接没有问题。
它们是这样的:

UsersJson(根元素)

1
2
3
4
5
public class UsersJson extends ResourceSupport {
    private List<UserJson> users;

    [... getters and setters ...]
}

UserJson

1
2
3
4
5
6
7
8
9
10
public class UserJson extends ResourceSupport {

    private Long identifier;

    private String firstName;

    private String lastName;

    [... getters and setters ...]
}

事实是,我期望jackson和spring足够聪明,可以解析_embedded属性并填充我的UsersJson.users属性,但事实并非如此。

我尝试了各种在Internet上找到的东西,但是我唯一能正常工作的是创建一个充当_embeddedpackage器的新类:

UsersJson(根元素)

1
2
3
4
5
6
public class UsersJson extends ResourceSupport {
    @JsonProperty("_embedded")
    private UsersEmbeddedListJson  embedded;

    [... getters and setters ...]
}

嵌入式"package器"

1
2
3
4
5
public class UsersEmbeddedListJson extends ResourceSupport {
    private List<UserJson> users;

    [... getters and setters ...]
}

它可以工作,但我觉得它很丑。

虽然我可以使用RestTemplate的以下配置(特别是当我在Jackson2HalModule中看到EmbeddedMapper时),但是却没有:

1
2
3
4
5
6
7
8
9
10
11
12
        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);

有人可以告诉我我在想什么吗?


最后,我找到了一种更好的使用这些应用程序/ hal json API的方法。

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

1
2
3
4
5
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();

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

这是我添加的Maven依赖项

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
    <dependency>
        <groupId>org.springframework.hateoas</groupId>
        spring-hateoas</artifactId>
        <version>0.19.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.plugin</groupId>
        spring-plugin-core</artifactId>
        <version>1.2.0.RELEASE</version>
    </dependency>
    <dependency>
        <groupId>com.jayway.jsonpath</groupId>
        json-path</artifactId>
        <version>2.0.0</version>
    </dependency>


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

1
2
3
4
@JsonProperty("_links")
public void setLinks(final Map<String, Link> links) {
    links.forEach((label, link) ->  add(link.withRel(label)) );
}

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


我不得不使用自定义设置程序扩展我的DTO POJO,以使用杰克逊作为映射器来解析REST客户端中Spring Hateos的输出:

HREF = " href ",并且REL作为常量为" rel "。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
@JsonProperty("link")
public void setLink(final List<Map<String, String>> links) {
    if (links != null) {
        links.forEach(l ->
                {
                    final String[] rel = new String[1];
                    final String[] href = new String[1];
                    l.entrySet().stream().filter((e) -> e.getValue() != null)
                            .forEach(e -> {
                                if (e.getKey().equals(REL)) {
                                    rel[0] = e.getValue();
                                }
                                if (e.getKey().equals(HREF)) {
                                    href[0] = e.getValue();
                                }
                            });
                    if (rel[0] != null && href[0] != null) {
                        add(new Link(href[0], rel[0]));
                    }
                }
        );
    }
}