spring-projects / spring-hateoas

Spring HATEOAS - Library to support implementing representations for hyper-text driven REST web services.
https://spring.io/projects/spring-hateoas
Apache License 2.0
1.05k stars 477 forks source link

Why change links from List<Link> to Map #479

Closed jiangchuan1220 closed 5 years ago

jiangchuan1220 commented 8 years ago

In ResourceSupport, links are declared as List. While in response body, links are transform to Map by a customized jackson ObjectMapper. Why do not keep links the same type (either List or map) in both ResourceSupport and response body? I am asking this question because this mismatch can lead to some automatical API description generator (e.g., swagger) can not know the transform and considers the links to be array in response body.

gregturn commented 8 years ago

Using List makes it very simple to build hypermedia.

By building a link via linkTo(methodOn(MyController.class).createEntry()).withRel("create") and then feeding it into Resources, we can leverage Java's "..." notation.

Imagine building a Map through a Java constructor call.

The truth is, we don't have to build the target mediatype. Internal types like Resources don't dictate that the output goes to HAL. Other mediatypes are possible (actually in the works once the affordances branch is complete) without binding the internal representation of body and links.

To be honest assuming that ResourceSupport maps 1-to-1 with HAL, SIREN, or whatever would be a faulty premise.

jiangchuan1220 commented 8 years ago

What is the problem of declare links as "Map" in ResourceSupport? Then the links type is consistent in API declare and real response. Currently the problem is that links is "List" in API declaration while in real response it is changed to "Map".

gregturn commented 8 years ago

I just listed several reasons and you simply repeated your original question.

gregturn commented 8 years ago

There are media types which output the links as a list not a map. Hence the API to build all the links is more important than one result type.

gregturn commented 7 years ago

Actually, to match perfectly with HAL, which is a map of listed links, the proper type for ResourceSupprt.links should be Map<String, List<Link>>. That would allow unpacking it perfectly for HAL.

{
    "_links": {
        "self": { "href": "/orders" },
        "curies": [{ "name": "ea", "href": "http://example.com/docs/rels/{rel}", "templated": true }],
        "next": { "href": "/orders?page=2" },
        "ea:find": {
            "href": "/orders{?id}",
            "templated": true
        },
        "ea:admin": [{
            "href": "/admins/2",
            "title": "Fred"
        }, {
            "href": "/admins/5",
            "title": "Kate"
        }]
    },

But not for Siren:

"links": [
    { "rel": [ "self" ], "href": "http://api.x.io/orders/42" },
    { "rel": [ "previous" ], "href": "http://api.x.io/orders/41" },
    { "rel": [ "next" ], "href": "http://api.x.io/orders/43" }
  ]

Siren has a list of links. Hence, altering the core structure of ResourceSupport.links doesn't appear likely, when to do so we would additionally be trading in Java 8 lists for Maps.

jiangchuan1220 commented 7 years ago

I see there are different kinds of links and it is difficult to summary them into one type. But the current solution has conflicts between the declaration and the actual response. I hope there would be a perfect solution for this issue in the future.

gregturn commented 7 years ago

Please clarify what conflict you are seeing in what mediatype between ResourceSupport and the resulting output. If this a bug in link generation in HAL, I would appreciate you describing what it is.

Apart from that, I believe accumulating a List of Link objects is sufficient for support of HAL, HAL-FORMS, Uber, SIREN, and Collection+JSON.