[MGNLREST-161] Delivery endpoint can return subnodes as an array Created: 15/Dec/17 Updated: 04/Apr/22 |
|
| Status: | Accepted |
| Project: | Magnolia REST Framework |
| Component/s: | None |
| Affects Version/s: | None |
| Fix Version/s: | None |
| Type: | New Feature | Priority: | Neutral |
| Reporter: | Richard Gange | Assignee: | Unassigned |
| Resolution: | Unresolved | Votes: | 7 |
| Labels: | None | ||
| Remaining Estimate: | Not Specified | ||
| Time Spent: | Not Specified | ||
| Original Estimate: | Not Specified | ||
| Issue Links: |
|
||||||||||||
| Template: |
|
||||||||||||
| Acceptance criteria: |
Empty
|
||||||||||||
| Release notes required: |
Yes
|
||||||||||||
| Documentation update required: |
Yes
|
||||||||||||
| Date of First Response: | |||||||||||||
| Epic Link: | Headless Backlog | ||||||||||||
| Story Points: | 8 | ||||||||||||
| Description |
|
Create a configuration option to allow subnodes to be returned as an array of nodes User story:
Notes: Currently the delivery endpoint returns subnodes directly as properties on the parent node, and then a '@nodes' array which includes the names of all of those properties. While this can have advantages when a developer is trying to access a specific node, (because they can just get it by its name) it makes the usecase of accessing lists of subnodes (such as areas, pages, blocks) harder because it adds a level of indirection. Practically in a React or Angular app this can be awkward. So much so that developers have asked us how to iterate over the nodes. Acceptance criteria:
Suggestion: Add the ability to define which nodetypes should be returned in arrays. Any node that is not in one of the specified types is still returned as a direct subnode. So if I specify:
Then the content will include a 'pages' and 'areas' arrays, which includes the subnodes contents. And any subnode NOT included in those arrays will still be included directly on the parent object, and still be listed in the @nodes array.
|
| Comments |
| Comment by Richard Gange [ 18/Dec/17 ] |
|
Example: From: {
"@name": "0",
"@path": "/jetBlue/header/0",
"TrueBlueNrtxt": "TrueBlue #",
"profileLinks": { *{color:red}//MultiValue Field{color}*
"@name": "profileLinks",
"@path": "/jetBlue/header/0/profileLinks",
"0": {
"@name": "0",
"@path": "/jetBlue/header/0/profileLinks/0",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/my-trueblue-home",
"LinkText": "Dashboard",
"@nodes": []
},
"1": {
"@name": "1",
"@path": "/jetBlue/header/0/profileLinks/1",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/account-info",
"LinkText": "My Profile",
"@nodes": []
},
"2": {
"@name": "2",
"@path": "/jetBlue/header/0/profileLinks/2",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/activity-history",
"LinkText": "My Activity",
"@nodes": []
},
"3": {
"@name": "3",
"@path": "/jetBlue/header/0/profileLinks/3",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/our-partners",
"LinkText": "Our Partners",
"@nodes": []
},
"4": {
"@name": "4",
"@path": "/jetBlue/header/0/profileLinks/4",
"linkType": "external",
"linkHref": "https://badges.jetblue.com/",
"LinkText": "My Badges",
"@nodes": []
},
"5": {
"@name": "5",
"@path": "/jetBlue/header/0/profileLinks/5",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/current-deals",
"LinkText": "CURRENT DEALS",
"@nodes": []
},
"6": {
"@name": "6",
"@path": "/jetBlue/header/0/profileLinks/6",
"linkType": "external",
"linkHref": "https://www.barclaycardus.com/",
"LinkText": "VIEW CREDITS",
"@nodes": []
},
"7": {
"@name": "7",
"@path": "/jetBlue/header/0/profileLinks/7",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/trueblue-faqs",
"LinkText": "FAQS",
"@nodes": []
},
"8": {
"@name": "8",
"@path": "/jetBlue/header/0/profileLinks/8",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/c/portal/logout",
"LinkText": "SIGN OUT",
"@nodes": []
},
"@nodes": [
"0",
"1",
"2",
"3",
"4",
"5",
"6",
"7",
"8"
]
},
"@nodes": [
"profileLinks"
]
}
To: {
"@name": "0",
"@path": "/jetBlue/header/0",
"TrueBlueNrtxt": "TrueBlue #",
"profileLinks": { *{color:red}// MultiValueFiled entires as array in @nodes{color}*
"@name": "profileLinks",
"@path": "/jetBlue/header/0/profileLinks",
"@nodes": [
{
"@name": "0",
"@path": "/jetBlue/header/0/profileLinks/0",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/my-trueblue-home",
"LinkText": "Dashboard",
"@nodes": []
},
{
"@name": "1",
"@path": "/jetBlue/header/0/profileLinks/1",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/account-info",
"LinkText": "My Profile",
"@nodes": []
},
{
"@name": "2",
"@path": "/jetBlue/header/0/profileLinks/2",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/activity-history",
"LinkText": "My Activity",
"@nodes": []
},
{
"@name": "3",
"@path": "/jetBlue/header/0/profileLinks/3",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/our-partners",
"LinkText": "Our Partners",
"@nodes": []
},
{
"@name": "4",
"@path": "/jetBlue/header/0/profileLinks/4",
"linkType": "external",
"linkHref": "https://badges.jetblue.com/",
"LinkText": "My Badges",
"@nodes": []
},
{
"@name": "5",
"@path": "/jetBlue/header/0/profileLinks/5",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/current-deals",
"LinkText": "CURRENT DEALS",
"@nodes": []
},
{
"@name": "6",
"@path": "/jetBlue/header/0/profileLinks/6",
"linkType": "external",
"linkHref": "https://www.barclaycardus.com/",
"LinkText": "VIEW CREDITS",
"@nodes": []
},
{
"@name": "7",
"@path": "/jetBlue/header/0/profileLinks/7",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/trueblue-faqs",
"LinkText": "FAQS",
"@nodes": []
},
{
"@name": "8",
"@path": "/jetBlue/header/0/profileLinks/8",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/c/portal/logout",
"LinkText": "SIGN OUT",
"@nodes": []
}
]
},
"@nodes": [
"profileLinks"
]
}
|
| Comment by Mikaël Geljić [ 07/May/18 ] |
|
FYI, the current format (child-objects + array of keys) was researched and done on purpose, for the lack of any information about the model.
Hope that helps, by the time we get proper content type modeling. |
| Comment by Antonio Tuor [ 18/Jun/18 ] |
|
At the moment, it's possible to change/extend the interface, to add additional configuration. With the current implementation of seperating the keys from the values, it's hard to traverse multiple nodes. This would be much easier by having an array of nodes or an map of <key, node> to traverse. |
| Comment by Will Scheidegger [ 27/Jun/18 ] |
|
Make it configurable please! The current behaviour is a very good "default" implementation. But I would suggest, that you add support for a "childNodes" configuration:
childNodeTypes:
- profileLink
- connection
childNodes:
- profileLinks:
isList: true
listName: bookmarks
{
"@name": "0",
"@path": "/jetBlue/header/0",
"TrueBlueNrtxt": "TrueBlue #",
"bookmarks": [
{
"@name": "0",
"@path": "/jetBlue/header/0/profileLinks/0",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/my-trueblue-home",
"LinkText": "Dashboard",
},
{
"@name": "1",
"@path": "/jetBlue/header/0/profileLinks/1",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/account-info",
"LinkText": "My Profile",
},
{
"@name": "2",
"@path": "/jetBlue/header/0/profileLinks/2",
"linkType": "external",
"linkHref": "https://trueblue.jetblue.com/group/trueblue/activity-history",
"LinkText": "My Activity",
}
],
"connections": {
"@name": "connections",
"@path": "/jetBlue/header/0/connections",
"0": {
"@name": "0",
"@path": "..."
},
"1": {
"@name": "1",
"@path": "..."
},
"@nodes": [
"0",
"1"
]
}
}
So if in childNodes you have a nodeName profileLinks which is set to isList: true, then the child nodes of the "profileLinks" node would be represented as list instead of a map. Optionally you could also modify the name of the list (in the example above the jcr node name "profileLinks" is renamed to "bookmarks" in the JSON output. For the "connections", no such setting is made. Therefore the standard data representation is used. I tried to do a little POC with a custom node writer. Unfortunately I could not get RestEasy to my writer as the class I sent it was always wrapped by the I18NContainerResponseFilter... |
| Comment by Mikaël Geljić [ 27/Jun/18 ] |
|
Hi will, sounds reasonable. |
| Comment by Will Scheidegger [ 28/Jun/18 ] |
|
Cool! When you're worried about mixed child nodes, you could add a "nodeType" property to that childNodes list configuration that would then filter the child nodes for a specified type. |
| Comment by Christopher Zimmermann [ 13/Nov/19 ] |
|
Bringing in information from |