4

We are in the middle of designing a new feature for our API and we stumbled across a dilemma.

We have two different types of resources with a 1-N relationship. Representations and Layers. A Representation can contain multiple Layers. A Layer can belong only to one Representation. The thing we are stuck with is that we need to maintain an order for the Layers in a Representation.

And we came up with two approaches:

First approach: Linked List

Each Layer knows about its previous layer. In the DB this is achieved by having a "parent" field in the Layers table that contains the id of another Layer. The first Layer will have a "parent" set to NULL.

This then is exposes through the API by the following URIs:

Create

GET /Representations/{repID}/layers

gets all the layers for a representation. The order can be worked out by going through all the layers and look at the Parent field.

POST /Representations/{repID}/layers

body: Label: (string) Parent: LayerId

This is used to create and insert a Layer in a specific position, by specifying the Parent in the request body. If you set Parent to NULL the newly created Layer will be the first Layer in the order. If you omit the Parent field, the newly created Layer will be positioned at the bottom of the order. Problem with this is that, in the response, we need to notify the api consumer that other layers have changed order because of the new insertion.

Update

PUT /Representations/{repID}/layers/{layerId}

body: Label: (string) Parent: LayerId Again you can specify a new Parent to re-order the layer and again we will need to send back some information about all the other layers that have changed.

Delete

DELETE /Representations/{repID}/layers/{layerId}

need to send back some information about all the other layers that have changed.

Second approach: Layers Order as its own resource

The idea is that layers themselves don't have a notion of order. They are merely a resource. Then you get a layersorder resource which is in charge of keeping the information about the order of the layers.

So you will still have the CRUD functionality for layers: GET - POST - PUT - DELETE

but when you want to know anything about their order, or you want to change their order, you will use the following uri:

/Representation/{repId}/layersorder

This resource will support only two methods

GET /Representations/{repID}/layersorder

gets back an ordered list of Layers Ids in this Representation.

PUT /Representations/{repID}/layersorder

body: [] - Array of Layers Ids in the new order. Updates the order of the layers. you need to pass an Array of Layers ids in the new order as the body of the request. (e.g. [1,3,2,4,6,5] )

as per the first approach, whenever you add or remove a Layer you will need to notify the api consumer that another resource has been updated. In the first approach that was the list of layers affected by the change, in this approach is the new order of the layers (the layersorder resource).

I would like to hear opinions and also examples of similar situations and how you solved the problem.

thanks.

Simone Vicentini
  • 259
  • 1
  • 2
  • 7
  • 1
    Just found this WebDAV draft regarding Ordered Collections http://tools.ietf.org/html/draft-ietf-webdav-ordering-protocol-10. It seems they are proposing a ORDERPATCH method where you can reorded a collection by specifying the new position for each collection member as first, last, before and after. – Simone Vicentini Feb 04 '13 at 11:28

1 Answers1

1

I've experienced part of what you are describing.

When doing a PUT/POST that affects an entity (or entities), I like to return the full object after the change. Hopefully the return object isn't massive, but if I were using your API, with the first approach ... I would enjoy doing a PUT/POST and updating a layer and then getting back the full Representation object with the updated Layer information.

It just makes it easy for me to confirm my changes and also start working immediately in my code with the new structure. I would dislike doing the PUT/POST and then having to do an additional GET to see the change.

For the second approach ... the more work I have to do to make an API call, the more frustrated I get. I'm not sure if I read it right, but to do a PUT with the second approach, it seems like I have to construct the entire representation and layer objects to update one piece of data. That would be frustrating.

I would prefer the syntax of the first approach, but with the concepts from the second. In other words, this is the document I would expect to see after a PUT/POST/GET:


{
   "type" : "Representation",
   "id" : 1,
   "layers" : [
      { "id" : 1, "name" : "the first layer", "order" : 1, "parent" : "" },
      { "id" : 2, "name" : "the second layer", "order" : 2, "parent" : 1 },
      { "id" : 3, "name" : "the third layer", "order" : 3, "parent" : 1 }   
   ]
}

It's sorted for me already so I don't have to do that work, but also has the information used to produce the sorting just in case. I've done this with REST APIs and it seems to work great for the users.

ryan1234
  • 7,237
  • 6
  • 25
  • 36
  • 1
    Hi Ryan, maybe I wasn't completely clear in the question, but with the second approach you don't have to send all the representation data. To reorder the layers you will just do a `PUT` to `/representations/{repId}/layersorder` and the body of the request would be `[10,22,33,11,67]` which is an ordered array of layers ids. – Simone Vicentini Jan 31 '13 at 09:04