-
Notifications
You must be signed in to change notification settings - Fork 472
Add support for specifying array serialization for a particular link relation #811
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
It looks like |
For some reason, there seems to be the same misunderstanding as in #288 - this isn't about rendering all link relations as an array, but rather explicitly defined, specific ones. |
We need more details. Is this to be applied for a particular controller? Or a particular domain class? |
Take a look at Section 2.1 from RFC 6573 (I also linked it in the issue description). Basically we want all our resources to contain Ideally, there would be a way to use |
Maybe I need to clarify: exposing a "_links": {
"item": [
{ "href": "http://localhost:8080/api/MyResource/1" }
]
} I.e. even a single link for an particular rel will be rendered as array. Is that not what you were after? You can see this being applied in |
Yes, but only for a specific link relations, not all. If we do what you suggest, we'd end up with: "_links": {
"first": [
{
"href": "http://localhost:8080/api/MyResource?page=1&size=2"
}
],
"last": [
{
"href": "http://localhost:8080/api/MyResource?page=3&size=2"
}
],
"next": [
{
"href": "http://localhost:8080/api/MyResource?page=2&size=2"
}
],
"item": [
{
"href": "http://localhost:8080/api/MyResource/1"
}
],
"self": [
{
"href": "http://localhost:8080/api/MyResource?page=1&size=2"
}
]
}, Which is clearly not desirable. We don't want |
Oh, I see. While I'd argue that that introduces inconsistency amongst the individual rels, we can certainly extend the configuration object to take a list of strings or patterns to force into arrays. |
Thanks for adding this to I understand your point about inconsistency between different relations, but IMO that's much less of a concern vs inconsistency between the same relation on different requests. If a certain relation is documented as an array, API consumers should know how to deal with it. |
If we could fit this into HalConfiguration (compared to annotating controllers or domain objects) it might simpler. Like
Something like this could signal “for this controller use arrays. And for that domain type do that as well. With this API, perhaps an annotation based approach could later be cultivated that populates this Wither. |
A rel is not really tied to a controller nor to a domain type. I guess we can provide a way to configure patterns to match, so that you can simplify the setup to configure this based on the curie used. |
I’m still waiting for the use case of why people need this one way in one place and another way elsewhere. |
@gregturn What else is needed, besides all the information already presented here, to clarify the uses for this?
With that in mind, current situation, where Concrete examples of current, undesirable situation:
$ http :8080/api/MyResource size==2 page==2
HTTP/1.1 200
Content-Type: application/application/hal+json;charset=UTF-8
Link: <http://localhost:8080/api/MyResource?page=1&size=2>; rel=first
Link: <http://localhost:8080/api/MyResource?page=1&size=2>; rel=prev
Link: <http://localhost:8080/api/MyResource?page=2&size=2>; rel=self
Link: <http://localhost:8080/api/MyResource?page=3&size=2>; rel=next
Link: <http://localhost:8080/api/MyResource?page=3&size=2>; rel=last
Link: <http://localhost:8080/api/MyResource/3>; rel=resources
Link: <http://localhost:8080/api/MyResource/4>; rel=resources
{
"_embedded": {
"item": [
{
"_links": {
"collection": {
"href": "http://localhost:8080/api/MyResource"
},
"self": {
"href": "http://localhost:8080/api/MyResource/3"
}
},
"attribute1": "value1",
"attribute2": "value2"
},
{
"_links": {
"collection": {
"href": "http://localhost:8080/api/MyResource"
},
"self": {
"href": "http://localhost:8080/api/MyResource/4"
}
},
"attribute1": "value1",
"attribute2": "value2"
}
]
},
"_links": {
"first": {
"href": "http://localhost:8080/api/MyResource?page=1&size=2"
},
"item": [
{
"href": "http://localhost:8080/api/MyResource/3"
},
{
"href": "http://localhost:8080/api/MyResource/4"
}
],
"last": {
"href": "http://localhost:8080/api/MyResource?page=3&size=2"
},
"next": {
"href": "http://localhost:8080/api/MyResource?page=3&size=2"
},
"prev": {
"href": "http://localhost:8080/api/MyResource?page=1&size=2"
},
"self": {
"href": "http://localhost:8080/api/MyResource?page=2&size=2"
}
},
"page": {
"number": 2,
"size": 2,
"totalElements": 5,
"totalPages": 3
}
}
$ http :8080/api/MyResource size==2 page==3
HTTP/1.1 200
Content-Type: application/application/hal+json;charset=UTF-8
Link: <http://localhost:8080/api/MyResource?page=1&size=2>; rel=first
Link: <http://localhost:8080/api/MyResource?page=2&size=2>; rel=prev
Link: <http://localhost:8080/api/MyResource?page=3&size=2>; rel=self
Link: <http://localhost:8080/api/MyResource?page=3&size=2>; rel=last
Link: <http://localhost:8080/api/MyResource/5>; rel=resources
{
"_embedded": {
"item": [
{
"_links": {
"collection": {
"href": "http://localhost:8080/api/MyResource"
},
"self": {
"href": "http://localhost:8080/api/MyResource/5"
}
},
"attribute1": "value1",
"attribute2": "value2"
}
]
},
"_links": {
"first": {
"href": "http://localhost:8080/api/MyResource?page=1&size=2"
},
"item": {
"href": "http://localhost:8080/api/MyResource/5"
},
"last": {
"href": "http://localhost:8080/api/MyResource?page=3&size=2"
},
"prev": {
"href": "http://localhost:8080/api/MyResource?page=2&size=2"
},
"self": {
"href": "http://localhost:8080/api/MyResource?page=3&size=2"
}
},
"page": {
"number": 3,
"size": 1,
"totalElements": 5,
"totalPages": 3
}
} |
@vpavic Your example says usage of "item" link relation is the criteria for applying
Then, anywhere |
Yes, that kind of configuration capability would be perfect for our use case. |
…ation. HalConfiguration now exposes a withSingleLinkRenderModeFor(…) taking a path pattern to be rendered in the also given RenderSingleLinks mode. It takes patterns as link relations are either plain strings or valid URIs. Simplified HAL link list rendering in Jackson2HalModule avoiding double nesting of collections before rendering.
…ation. HalConfiguration now exposes a withSingleLinkRenderModeFor(…) taking a path pattern to be rendered in the also given RenderSingleLinks mode. It takes patterns as link relations are either plain strings or valid URIs. Simplified HAL link list rendering in Jackson2HalModule avoiding double nesting of collections before rendering.
Resolved via aea4c4c. |
@odrotbohm @gregturn Do you have any suggestions on how to work around this on I've been poking around on few occasions but haven't been able to find a reasonable way to override logic in |
The currently implementation is subawesome. Specifying a relation key which will be rendered as an array across the whole application? This means that you have to define unique links because you don't want to conflict
with the |
Why don’t you open a new ticket instead of commenting on one that’s been closed and released. |
This is a follow-up on #288, as suggested in last comment on that issue.
We're including
item
link relation (see https://tools.ietf.org/html/rfc6573#section-2.1) to_links
in our HAL responses that return collections/pages.The code that handles this in
@Controller
handler method looks something like this:This works fine when actually there are multiple resource in the collection/page:
However, when there is a single resource in the collection/page, then we don't get an array:
Obviously, this isn't ideal from the perspective of client that consumes the service. It would be nice if Spring HATEOAS would provide a support for explicitly specifying array serialization for a certain link relations.
The text was updated successfully, but these errors were encountered: