Active_model_serializers: Serializer with relationship serializer not working with json_api adapter

Created on 16 Aug 2015  路  9Comments  路  Source: rails-api/active_model_serializers

I am trying to use custom serializers in my relationship, and they seem to work with the custom adapter, however, when I specify the json_api adapter in an initializer, they stop to work.

Here is my serializer:

module Api
  module V1
    module Serializers
      class PostSerializer < ActiveModel::Serializer
        attributes :title, :id

        belongs_to :author, serializer: UserSerializer
        has_many :post_sections, serializer: PostSectionSerializer
      end
    end
  end
end

When I use the json_api adapter the relationships return empty data sets (just id and type attributes), when I use the default adapter everything works fine. Is that a bug or am I not getting something ?

EDIT: SO question: http://stackoverflow.com/questions/32036253/active-model-serializer-not-working-with-json-api-adapter

Most helpful comment

Hey @thecritic,

It is works fine for me. Relationships only returns id and type according to json-api exmaples. If you need to return more information about this relation you should add include option on your render action.

This adapter follows 1.0 of the format specified in
jsonapi.org/format. It will include the associated
resources in the "included" member when the resource names are included in the
include option.

  render @posts, include: ['authors', 'comments']
  # or
  render @posts, include: 'authors,comments'

Ex.

def show
  render json: @post, include: 'comments'
end

and then, output:

{
    "data": {
        "id": "1",
        "type": "post",
        "attributes": {
            "title": "bla",
            "content": "bla"
        },
        "relationships": {
            "comment": {
                "data": [
                    {
                        "type": "comments",
                        "id": "1"
                    }
                ]
            }
        }
    },
    "included": [
        {
            "id": "1",
            "type": "comments",
            "attributes": {
                "title": "test",
                "content": "test"
            }
        }
    ]
}

Let us know if it works for you as well. :smile:

All 9 comments

Hey @thecritic,

It is works fine for me. Relationships only returns id and type according to json-api exmaples. If you need to return more information about this relation you should add include option on your render action.

This adapter follows 1.0 of the format specified in
jsonapi.org/format. It will include the associated
resources in the "included" member when the resource names are included in the
include option.

  render @posts, include: ['authors', 'comments']
  # or
  render @posts, include: 'authors,comments'

Ex.

def show
  render json: @post, include: 'comments'
end

and then, output:

{
    "data": {
        "id": "1",
        "type": "post",
        "attributes": {
            "title": "bla",
            "content": "bla"
        },
        "relationships": {
            "comment": {
                "data": [
                    {
                        "type": "comments",
                        "id": "1"
                    }
                ]
            }
        }
    },
    "included": [
        {
            "id": "1",
            "type": "comments",
            "attributes": {
                "title": "test",
                "content": "test"
            }
        }
    ]
}

Let us know if it works for you as well. :smile:

@thecritic it's as @bacarini just said, you may also include chained associations by using:

render @posts, include: ['authors.profile', 'comments']

@bacarini could you please add the same response to the SO question? :smile: It might be easier for other to find as well.

Hi @bacarini!
First of all, thanks for your reply. Yes I knew about includes and I went this route and it does make sense when I think about it (one wouldn't want to always include the fully fleshed out objects in the response data without explicitly specifying includes...), but isn't there a way to specify that these objects should be fully fleshed out within the relationships ? Or is this expected behavior ? But isn't it kind of overkill if you had both resource identifier objects and includes in there ? There is kind of a redundancy issue there, no ?

So @thecritic, this is the expected behavior, because it follows the json-api conventions, as you can see by the chain bellow, it does not support an attributes key.

  • relationships: a relationships object describing relationships between the resource and other JSON API resources.

A relationship object MUST contain at least one of the following:
...

  • data: resource linkage

Resource linkage MUST be represented as one of the following:
...

  • A "resource identifier object" MUST contain type and id members.

I know it might seems an overkill, but the idea is to force you to keep it simple. I honestly don't think it's an overkill if you need it, because the id and type on the relationships represents simplest image of the object you are retrieving and it's associations.

@joaomdmoura I could imagine that you could infer the relationship objects from the includes ? I thought that the set of includes overlaps with the relationship objects, which is where the redundancy comes in. Well I guess there is a good reason for doing it this way, so not going to further question this approach. Thanks @joaomdmoura and @bacarini for pointing me into the right direction and solving my problems! Much appreciated!

We do not infer the relationship from the includes because you can also include other objects that are not related to the original object, as in:

render @posts, include: ['authors.profile']

I think this is a suitable question but more related to json-api itself, they have a pretty active project and are really friendly in case you want to open an issue there to question about it :smile: https://github.com/json-api/json-api

:+1: :smiley:

@joaomdmoura @bacarini I now fully understand what's happening there (Re-read the JSON 1.0 Format, now it's clear why it is the way it is... ), however do I understand correctly that I have to aggregate the data myself ? So, with the "conventional" JSON format I could just access the relationships, for example post.post_sections would be an array and I could just simply iterate over it. With the 1.0 format I would have to implement some logic -- which inevitably creates overhead on the client -- myself to aggregate the data so that I can use it like the old format, i.e. go through the relationships first, find the includes by type and id and flesh them out myself before using them ? That seems kind of complicated... Is that the case ?

I'm not sure I got it, but you could use other adapter than the json_api, like the usual flatten_json or the json one, this would not follow json-api conventions but would work really well.

Was this page helpful?
0 / 5 - 0 ratings