jsonapi-rb / jsonapi-deserializable

Conveniently deserialize JSON API payloads into custom hashes.
http://jsonapi-rb.org
MIT License
26 stars 20 forks source link

Deserializing a Compound document #19

Open oeyiowuawi opened 6 years ago

oeyiowuawi commented 6 years ago

Hi

I tried deserializing a compound json api document with the gem and found out this isn't supported as of now. For example, if the payload looks like this

{
  "data": [{
    "type": "articles",
    "id": "1",
    "attributes": {
      "title": "JSON API paints my bikeshed!"
    },
    "links": {
      "self": "http://example.com/articles/1"
    },
    "relationships": {
      "author": {
        "links": {
          "self": "http://example.com/articles/1/relationships/author",
          "related": "http://example.com/articles/1/author"
        },
        "data": { "type": "people", "id": "9" }
      },
      "comments": {
        "links": {
          "self": "http://example.com/articles/1/relationships/comments",
          "related": "http://example.com/articles/1/comments"
        },
        "data": [
          { "type": "comments", "id": "5" },
          { "type": "comments", "id": "12" }
        ]
      }
    }
  }],
  "included": [{
    "type": "people",
    "id": "9",
    "attributes": {
      "first-name": "Dan",
      "last-name": "Gebhardt",
      "twitter": "dgeb"
    },
    "links": {
      "self": "http://example.com/people/9"
    }
  }, {
    "type": "comments",
    "id": "5",
    "attributes": {
      "body": "First!"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "2" }
      }
    },
    "links": {
      "self": "http://example.com/comments/5"
    }
  }, {
    "type": "comments",
    "id": "12",
    "attributes": {
      "body": "I like XML better"
    },
    "relationships": {
      "author": {
        "data": { "type": "people", "id": "9" }
      }
    },
    "links": {
      "self": "http://example.com/comments/12"
    }
  }]
}

One would have to manually to iterate over the data key and feed each resource into the Article deserializer.

class DeserializableArticle < JSONAPI::Deserializable::Resource
   has_one :author
    has_many :comments do | link, ids, types | do
       ....
    end
end

doc = JSON.parse(document)
doc["data"].map do |resource|
  DeserializableArticle.call(resource)
end

But going this way would mean other top level document related resources(the included key) wouldn't be available in the has_many block defined in the deserializer. Is there a way to get the related resources added in the included top-level part of the document into the has_many/has_one block so we can easily get all the needed data deserialized together?

poteto commented 6 years ago

@oeyiowuawi I have a working branch with support for deserializing 1 level of includes - https://github.com/poteto/jsonapi-deserializable/commit/9a8cd7a2f0b3fc446e6972a1b6b306c4b62366fc

oeyiowuawi commented 6 years ago

@poteto Thanks for your response. I've checked out the working branch and that would work for a single resource. What I'm really looking for is when data is an array of resources. how we can deserialize those resources with the included resources.

vaihtovirta commented 6 years ago

Hey @poteto Are you planning to open a pull request with your changes?

broosk1993 commented 1 year ago

I have added this PR that supports what you need.

Waiting for @beauby to review.