I have an author that has many books and a book that belongs to an author in an rails 7 api. I am using "jsonapi-serializer", "~> 2.2" to try and get the author and their books. When I look at the json file, I get this:
{
"id": "1",
"type": "author",
"attributes": {
"id": 1,
"fname": "John",
"lname": "Doe"
},
"relationships": {
"books": {
"data": [
{
"id": "1",
"type": "books"
},
{
"id": "2",
"type": "books"
},
{
"id": "3",
"type": "books"
},
{
"id": "4",
"type": "books"
},
{
"id": "5",
"type": "books"
}
]
}
}
}
I want to expand what is in relationships to show the full information or at least customize it so that it shows something like id, name, release_year rather than just id and type. I don't want to have to make another database query to get the books.
The AuthorSerializer looks like this:
class AuthorSerializer
include JSONAPI::Serializer
attributes :id, :fname, :lname
has_many :books
end
The BookSerializer looks like this:
class BooksSerializer
include JSONAPI::Serializer
attributes :id, :name, :release_year, :awards, :genre, :price, :blurb, :isbn
belongs_to :author
end
The Author controller looks like this:
class AuthorController < ApplicationController
before_action :set_author, only: %i[ show update destroy ]
# GET /authors
def index
@authors = Author.includes(:books).all
render json: AuthorSerializer.new(@authors)
end
# GET /authors/1
def show
render json: AuthorSerializer.new(@author)
end
# POST /authors
def create
@author = Author.new(hospital_params)
if @author.save
render json: @author, status: :created, location: @author
else
render json: @author.errors, status: :unprocessable_entity
end
end
# PATCH/PUT /authors/1
def update
if @author.update(author_params)
render json: @author
else
render json: @author.errors, status: :unprocessable_entity
end
end
# DELETE /authors/1
def destroy
@author.destroy
end
private
# Use callbacks to share common setup or constraints between actions.
def set_author
@author= Author.find(params[:id])
end
# Only allow a list of trusted parameters through.
def author_params
params.require(:author).permit(:id, :fname, :lname, :avatar[])
end
end
What you are asking for violates the JSON:API spec.
relationships
: a relationships object describing relationships between the resource and other JSON:API resources.
“relationship object” MUST contain at least one of the following: ... data: resource linkage
Resource linkage MUST be represented as one of the following: ... an array of resource identifier objects for non-empty to-many relationships.
A “resource identifier object” is an object that identifies an individual resource.
A “resource identifier object” MUST contain a
type
member. It MUST also contain anid
member... A “resource identifier object” MAY also include ameta
member, whose value is a meta object that contains non-standard meta-information.
As you can see a Resource Identifier cannot contain anything more than type
, id
, and meta
(other than non persisted objects which must contain lid
in place of id
)
The jsonapi-serializer
gem strictly adheres to the spec and only returns the "Resource Identifier Objects" i.e. type
and id
(Code Source)
You could use AuthorSerializer.new(@authors, include: [:books])
which will add the Book
objects to the included
member but it is definitely not the cleanest representation
Example:
{:data=>
{:id=>"1",
:type=>:author,
:attributes=>{:id=>1, :fname=>"John", :lname=>"Doe"},
:relationships=>
{:books=>
{:data=>
[{:id=>"1", :type=>:book},
{:id=>"2", :type=>:book},
{:id=>"3", :type=>:book},
{:id=>"4", :type=>:book},
{:id=>"5", :type=>:book}]}}},
:included=>
[{:id=>"1",
:type=>:book,
:attributes=>{:id=>1, :name=>"Book 1", :release_year=>2011},
:relationships=>{:author=>{:data=>{:id=>"1", :type=>:author}}}},
{:id=>"2",
:type=>:book,
:attributes=>{:id=>2, :name=>"Book 2", :release_year=>2012},
:relationships=>{:author=>{:data=>{:id=>"1", :type=>:author}}}},
{:id=>"3",
:type=>:book,
:attributes=>{:id=>3, :name=>"Book 3", :release_year=>2013},
:relationships=>{:author=>{:data=>{:id=>"1", :type=>:author}}}},
{:id=>"4",
:type=>:book,
:attributes=>{:id=>4, :name=>"Book 4", :release_year=>2014},
:relationships=>{:author=>{:data=>{:id=>"1", :type=>:author}}}},
{:id=>"5",
:type=>:book,
:attributes=>{:id=>5, :name=>"Book 5", :release_year=>2015},
:relationships=>{:author=>{:data=>{:id=>"1", :type=>:author}}}}
]}