yaks/lib/yaks/reader/json_api.rb
module Yaks
module Reader
class JsonAPI
def call(parsed_json, _env = {})
included = parsed_json['included'].nil? ? {} : parsed_json['included'].dup
if parsed_json['data'].is_a?(Array)
CollectionResource.new(
attributes: parsed_json['meta'].nil? ? nil : {meta: parsed_json['meta']},
members: parsed_json['data'].map { |data| call('data' => data, 'included' => included) }
)
else
attributes = parsed_json['data'].dup
links = attributes.delete('links') || {}
relationships = attributes.delete('relationships') || {}
type = attributes.delete('type')
attributes.merge!(attributes.delete('attributes') || {})
embedded = convert_embedded(Hash[relationships], included)
links = convert_links(Hash[links])
Resource.new(
type: Util.singularize(type),
attributes: Util.symbolize_keys(attributes),
subresources: embedded,
links: links
)
end
end
def convert_embedded(relationships, included)
relationships.flat_map do |rel, relationship|
# A Link doesn't have to contain a `data` member.
# It can contain URLs instead, or as well, but we are only worried about *embedded* links here.
data = relationship['data']
# Resource data MUST be represented as one of the following:
#
# * `null` for empty to-one relationships.
# * a "resource identifier object" for non-empty to-one relationships.
# * an empty array ([]) for empty to-many relationships.
# * an array of resource identifier objects for non-empty to-many relationships.
if data.nil?
NullResource.new(rels: [rel])
elsif data.is_a? Array
if data.empty?
NullResource.new(collection: true, rels: [rel])
else
CollectionResource.new(
members: data.map { |link|
data = included.find{ |item| (item['id'] == link['id']) && (item['type'] == link['type']) }
call('data' => data, 'included' => included)
},
rels: [rel]
)
end
else
data = included.find{ |item| (item['id'] == data['id']) && (item['type'] == data['type']) }
call('data' => data, 'included' => included).with(rels: [rel])
end
end.compact
end
def convert_links(links)
links.map do |rel, link|
Resource::Link.new(rel: rel.to_sym, uri: link)
end
end
end
end
end