jasminb / jsonapi-converter

JSONAPI-Converter is a Java/Android library that provides support for working with JSONAPI spec
Apache License 2.0
273 stars 81 forks source link

Eager vs Lazy resolution of relationships #31

Open emetsger opened 8 years ago

emetsger commented 8 years ago

The current behavior of the JSON-API Converter when resolving relationships is to resolve them eagerly, and recursively.

If you have a model that represents a hierarchy of objects that is arbitrarily deep, resolving a single object in that hierarchy will result in recursivly resolving all of the nodes below it.

For example, retrieving an instance of Node, below, may result in traversing a hierarchy that is arbitrarily deep:

Example Java

@Types("node")
class Node {

  @Id
  String id;

  @Relationship(value = "children", resolve = true, relType = RelType.RELATED)
  List<Node> children;

  // ...
}

Example JSON

{
  "data": [
    {
      "type": "node",
      "id": "1",
      "relationships": {
        "children": {
          "links": {
            "related": "http://example.com/node/1/children"
          }
        }
      }
    }
  ]
}

This behavior may not be desirable for many reasons, least of which have to do with the performance of retrieving deeply nested structures.

There may be multiple ways to address this. For example:

jasminb commented 8 years ago

Hey,

I've considered lazy loading already. Having in mind that lib is used for android dev also and networking restrictions that come with it, executing lazy resolution becomes really tricky.

emetsger commented 8 years ago

Hey @jasminb, so I put together a proposed approach:

@Type("foo")
class Foo {
    @Id
    String id;

    @Relationship(value = "...", resolve = true, strategy = ResolutionStrategy.REF)
    String relRef;
}

If the @Relationship uses a strategy of ResolutionStrategy.REF, the url of the relationship is stored instead of resolving and deserializing the response document.

If the @Relationship uses a strategy of ResolutionStrategy.OBJECT the url of the relationship is resolved and deserialized like normal.

Essentially, this is implementing the third bullet point from above:

Instead of resolving the URL and deserializing the response document to a Java object, simply save the URL as a string in the Java model. This is essentially lazy loading, which puts the burden of resolving and deserializing a reference explicitly on the developer of the model.