Sub resources, inline collections, and the like

499 views
Skip to first unread message

Luke Stokes

unread,
Oct 3, 2012, 12:41:08 PM10/3/12
to collect...@googlegroups.com
Hey Mike.

I'm tinkering with the idea of supporting Collection+JSON for the API I'm working on, and I was a little confused last night with how to properly represent sub resources. Siren and HAL have "entities" and "_embedded" and when I was looking to map what we have into something similar for HAL, I got stuck.

I've read these:


Is the inline collections the way to go? The value of the json node there would be a fully complete Collections representation, correct? Is that something that is officially supported or being evaluated as a future addition/extension?

I'm also thinking it may simply be a different paradigm you have here. One collection with one template. When things are made up of multiple layers, I see how it can get more complex. So far with our API, we have a number of resources that contain sub resources because they are almost always wanted together (transactions + payments + attributes, customers + customer addresses, etc, etc) We've broken some things out in the API response to move towards future functionality as well (as an example: we currently only support one payment gateway method per transaction, but we're moving towards payment gateway sets, i.e. going from a "one" to a "many" situation).

We could probably do everything as a single level collection, but that might include quite a bit of chattiness.

Thoughts?

mca

unread,
Oct 3, 2012, 12:54:07 PM10/3/12
to collect...@googlegroups.com
Luke:

I don't recommend the "inline collections" style of representation. Yehuda Katz posted the extension for JC and I am not sure if he's using it (likely not). IMO, this is an "optimization" that is not really needed. It adds complexity to the client that I think is not needed. I reality you will make a call for additional collections and cache that result. the cost is relatively low, IMO.

Now, if it turns out your model makes extensive use of this sub-collection pattern, it's rather easy to model that directly in the items collection using the same basic techniques of Couch and other NSQL-style storage models: use a "type" data element that identifies the type of item and another data element ("parent") to indicate the relationship. Then you can represent both parent and child items in the same response and let the client sort out how to render them.

For example, the items:[] collection can contain 3 members with the "type" set to "invoice" and 9 members with the "type" set to "line-item" and the "line-item" membesr can have a "parent" value that points to the id or URI of the associated invoice type items. This is leveraging the desing of CJ rather than the design of an object graph in your problem domain, etc.

Just a thought.

mca

Viswanath Durbha

unread,
Oct 5, 2012, 7:55:18 AM10/5/12
to collect...@googlegroups.com
A couple of basic questions.

1. If the collection object can contain invoices and line items, how will the client figure out whether the template provided is to update a line item or invoice? Do we have to use the templates extension to provide multiple templates?

2. When posting a new item to the collection, how should the client specify the parent item relation?

Thanks,
Vishi

mca

unread,
Oct 5, 2012, 8:20:56 AM10/5/12
to collect...@googlegroups.com
first, in many cases, adding item lists that contain multiple "types" (invoice header & invoice lineitem) need not *require* multiple write templates. for this example, you might define a template that contains both items and header.

second, yes, you can level-up to using the template collection extension where you can include rel information for each template to aide your client processing.

third, you can add the same data element ("type=parent") to the template to indicate relationship. you can use URIs to help sort out relationship on the server (/invoices/{inv-id}/lines/{line-id} or /invoices{inv-id+line+id}, etc.) or you can use a data point in the template to indicate the parent (data:[{name: "parent", value:"{parent-href}"}...]

there are lots of options here and you can use the one that best fits the current use case.

Luke Stokes

unread,
Oct 10, 2012, 1:40:48 PM10/10/12
to collect...@googlegroups.com
Thanks Mike. I guess I was thinking anything related to hypermedia or link relationships had to be defined within the hypermedia spec. If I'm understanding you correctly, your recommendation is to just add whatever JSON keys and values needed to properly represent the data and stuff some links in there which would then have to be documented separately, right?

I guess what I like about an inline approach is that it still keeps with the existing syntax for hypermedia.

Sounds like things are flexible either way. Thanks!

mca

unread,
Oct 10, 2012, 2:58:18 PM10/10/12
to collect...@googlegroups.com

I would be really interested in a comparison between the in line extension and using the method I talked about.

both from the performance perspective at runtime and the developer optimization.

keep me posted as you work through this.

Mike Amundsen

Glenn Block

unread,
Nov 25, 2012, 11:56:33 AM11/25/12
to collect...@googlegroups.com
Hi all, new to the group

Mike, I had a similar question recently, so to recap basically you are proposing representing a hierarchy (if you need to) within the flat data structure with some elements being parents and some children with pointers in between?

Thanks
Glenn

mca

unread,
Nov 25, 2012, 12:03:15 PM11/25/12
to collect...@googlegroups.com
GB:

good to see you here.

well, my response to Luke (and others in the past) has been to "resist" adding nested collections to CJ. it adds complexity to the parse/render work and i'm not sure it is needed. that's my *starting* position<g>.

but i'm totally open to seeing some examples of how nesting works w/ CJ, how it affects existing client apps, how the code looks diff, perf issues, etc.

right now, i think the same effect can be achieved by adding a data element in the list that indicates a type of "grouping" - something that most nested collections exhibit.


items: [
  {
     href : "...",
     data : [ group : "invoice", ...]
  },
  {
    href : "...",
    data : [ group : "invoice-detail", ...]
  },
  ...
]

IOW, instead of *physical* nesting in the same response, "logical" nesting using a value in the item. this layout is no larger then a response that contains physical nesting, it still parses/renders for all existing clients, and it gives "custom clients" the ability to customize the rendering based on group if that's what they want to present.

just my idea anyway.

Greg Knapp

unread,
Nov 6, 2013, 9:53:50 AM11/6/13
to collect...@googlegroups.com
Sorry to dig up an old thread. Luke system is very similar to one I am building, a payment reporting API with transactions, services and clients.

The services in my system have a collection of properties. One property is a collection itself, the cards accepted on the service.

In plain old JSON this is structured as:

{
"service": {
  "id": 24751,
  "name": "My service",
  "client_id": 9,
  "gateway": "https://www.example.com/payment.wsdl",
  "cards": [
    {"scheme": "VISA", "type": "debit", "accepted": 1},
    {"scheme": "VISA", "type": "credit", "accepted": 1},
    {"scheme": "MasterCard", "type": "debit", "accepted": 1},
    {"scheme": "MasterCard", "type": "credit", "accepted": 1},
    {"scheme": "American Express", "type": "credit", "accepted": 0},
    {"scheme": "Diners Club", "type": "credit", "accepted": 0}
  ]
}
}

I am struggling to adhere to c+j in this instance. Instead of attempting to inline this information, I tried to separate out the cards into a linked relation.

Service:

{
  "collection": {
    "version": "1.0",
    "href": "/admin/service/24751",
    "items": [
      {
        "href": "/admin/service/24751",
        "data": [
          {"name": "id", "value": 24751},
          {"name": "name", "value": "My service"},
          {"name": "clientId", "value": 9},
          {"name": "gateway", "value": "https://www.example.com/payment.wsdl"}
        ],
        "links": [{"rel": "cards", "href": "/admin/service/24751/cards"}]
      }
    ]
  }
}

Cards:

{
  "collection": {
    "version": "1.0",
    "href": "/admin/service/24751/cards",
    "items": [
      {
        "href": "/admin/service/24751/cards/<id>",
        "data": [
          {"name": "scheme", "value": "VISA"},
          {"name": "type", "value": "debit"},
          {"name": "accepted", "value": 1}
        ]
      },
      {
        "href": "/admin/service/24751/cards/<id>",
        "data": [
          {"name": "scheme", "value": "VISA"},
          {"name": "type", "value": "credit"},
          {"name": "accepted", "value": 1}
        ]
      },
      ...
    ]
  }
}

In the spec, section 4.1 (items) says and item SHOULD contain an href. What does that mean? SHOULD is ambiguous vs MUST (required) and MAY (optional). As it happens I don't have an appropriate end point for individual accepted card fields, they are not items by themselves, just properties of a service. I have no internal identifier for them.

Does SHOULD mean I am free to exclude the "href" field from my items in this instance?

Thanks

mca

unread,
Nov 6, 2013, 9:58:26 AM11/6/13
to collect...@googlegroups.com
yes, you are free to *not* include an HREF for an item. that means you have a list and no way to address, edit, or delete individual members of that list.

BTW - the "<id>" elements of the "/admin/service/24751/cards/<id>" string are invalid URLs here. you might be doing some short-hand for this example in the thread, but at runtime, that would be invalid.



mca

--
You received this message because you are subscribed to the Google Groups "Collection+JSON" group.
To unsubscribe from this group and stop receiving emails from it, send an email to collectionjso...@googlegroups.com.
For more options, visit https://groups.google.com/groups/opt_out.

Greg Knapp

unread,
Nov 6, 2013, 10:11:39 AM11/6/13
to collect...@googlegroups.com
Thanks Mike,

Yes it was short hand just for this post. I've also just looked closer at your C+J docs and seen the link to RFC2119 for "SHOULD", "MAY", "MUST" etc.

Interesting point about no ability to edit those fields. It's not needed via this API (at present), will give that some thought for the future.

mca

unread,
Nov 6, 2013, 10:15:21 AM11/6/13
to collect...@googlegroups.com
Keep me posted on how things are going. always interested in feedback and experience stories.

Cheers.

--

Larry Marburger

unread,
Nov 6, 2013, 10:29:56 AM11/6/13
to collect...@googlegroups.com
On Wed, Nov 6, 2013 at 9:53 AM, Greg Knapp <virtua...@gmail.com> wrote:
I am struggling to adhere to c+j in this instance. Instead of attempting to inline this information, I tried to separate out the cards into a linked relation.

Another option is to use an assorted collection. Mike's been preaching their usage for a while but I only recently learned how powerful they are.

An assorted collection might look something like this:

{
  "collection": {
    "version": "1.0",
    "href": "/admin/service/24751",
    "items": [
      {
        "href": "/admin/service/24751",
        "data": [
          {"name": "kind", "value": "service"},
          {"name": "id", "value": 24751},
          {"name": "name", "value": "My service"},
          {"name": "clientId", "value": 9},
          {"name": "gateway", "value": "https://www.example.com/payment.wsdl"}
        ]
      },
      {
        "data": [
          {"name": "kind", "value": "card"},
          {"name": "scheme", "value": "VISA"},
          {"name": "type", "value": "debit"},
          {"name": "accepted", "value": 1}
        ]
      },
      {
        "data": [
          {"name": "kind", "value": "card"},
          {"name": "scheme", "value": "VISA"},
          {"name": "type", "value": "credit"},
          {"name": "accepted", "value": 1}
        ]
      },
      ...
    ]
  }
}

(Since "type" is used by cards, I used "kind" instead. I'm sure you can come up with a better name for this attribute.)

-- 
Larry Marburger
Homeopathic Code Remedyologist

Greg Knapp

unread,
Nov 6, 2013, 12:47:40 PM11/6/13
to collect...@googlegroups.com, la...@marburger.cc
Thanks Larry, also very useful.

Dennis Roof

unread,
Dec 13, 2013, 10:37:53 AM12/13/13
to collect...@googlegroups.com
Does it make sense to add multiple groups to an item in an assorted collection to both group items together and imply a hierarchy using groups in groups? Or is it a better idea to imply a hierarchy using a parent-href field in items?

In case of groups in groups to hint a hierarchy among items, I'd have to use item IDs in the group names to separate multiple hierarchies in an assorted item collection.



Op zondag 25 november 2012 18:03:36 UTC+1 schreef Mike Amundsen:
Reply all
Reply to author
Forward
0 new messages