The "self" link is often not very useful if you have just fetched the document from that URI. As you say, you already have the URI, so what does the "self" link provide?
However, it is more useful when you opened the data from somewhere else, and do not know the URI for it. In that case, the "self" link is just a way of specifying that URI from the item data.
It's also useful when you have composite data. For instance, say we have this document fetched from /rooms/4:
{
"roomId": 4,
"name": "The lobby",
"furniture": [
{
"furnitureId": 3563,
"roomId": 4,
"name": "Receptionist's desk",
"type": "desk",
...
},
{
"furnitureId": 2031,
"roomId": 4,
"name": "A wheely chair",
"type": "chair",
...
},
]
}
This document contains the full details of all the furniture in that room, bundled up inside it. However, if I want to interact with a particular piece of furniture, how do I do that? I could use a JSON Pointer fragment, but then if I moved a piece of furniture from one room to the other, nobody else could tell it was the same piece of furniture.
So I define a "self" link on the furniture items:
{
"title": "Room",
"type": "object",
"properties": {
"furniture": {
"type": "array",
"items": {
"title": "Furniture",
"type": "object",
"properties": { ... },
"links": [
{
"rel": "self",
"href": "/furniture/{furnitureId}"
},
{
"rel": "parent",
"href": "/room/{roomId}"
}
]
}
}
}
}
Now, if I want to move the wheely chair to another room, I don't have to delete the one in the lobby, and create a new one somewhere else, because this chair has a unique URI of its own. And what's more, I know this URI, even though it was served up to me embedded inside another document.
So I can probably just modify the chair itself using a PUT request:
PUT /furniture/2031
{
"furnitureId": 2031,
"roomId": 15,
"name": "The wheely chair from the lobby",
"type": "chair",
...
}
Presumably, the server would at this point stop including the chair in the furniture listing for the lobby (#4), and start including it in a different room (#15).