Skip to content

Instantly share code, notes, and snippets.

@tjheeta
Last active August 29, 2015 14:22
Show Gist options
  • Save tjheeta/ae63f068656dddb03098 to your computer and use it in GitHub Desktop.
Save tjheeta/ae63f068656dddb03098 to your computer and use it in GitHub Desktop.
First pass for Ecto -> Json API - WIP
defmodule JsonApi do
def filter_struct(obj) do
is_struct?(obj) or (is_list(obj) && is_struct?(Enum.at(obj,0)))
end
def is_struct?(obj) do
is_map(obj) && Map.get(obj, :__struct__) != nil
# ( obj.__struct__ == Ecto.Association.NotLoaded ||
end
def json_api(obj) do
if is_list(obj) do
data = Enum.map(obj, &json_api_data(&1))
%{ data: data }
else
json_api_data(obj)
end
end
def json_api_data(obj, filter \\ []) do
# Go one level deep while splitting out the structs
# If it's a struct, it should be under relationships and includes
{structures, attributes} =
Map.drop(obj, [:__meta__, :__struct__])
|> Enum.partition( fn{k,v} ->
filter_struct(v)
end)
attributes = attributes |> Enum.into(%{})
# Parse the structures to give some relationships
relationships =
structures
|> Enum.map( fn{k,v} ->
if ! is_list(v), do: v = [v]
data = Enum.reduce(v, [], fn(x, acc) ->
id = Map.get(x,:id)
if id, do: acc = acc ++ [%{"type": to_string(k), "id": id}]
end)
data
end)
|> List.flatten
|> Enum.reject(&is_nil(&1))
# Ugly, but go over the included set from the structures one more time
included =
structures
|> Enum.map( fn{k,v} ->
if ! is_list(v), do: v = [v]
data = Enum.reduce(v, [], fn(x, acc) ->
id = Map.get(x,:id)
# find everything that isn't a struct and put it into a map
attributes=
x
|> Map.drop([:__meta__, :__struct__])
|> Enum.reject(fn{k,v} ->
filter_struct(v)
end)
|> Enum.into(%{})
if id, do: acc = acc ++ [%{"type": x.__meta__.source, "id": id, "attributes": attributes}]
end)
data
end)
|> List.flatten
|> Enum.reject(&is_nil(&1))
# Generate first level object
%{
type: obj.__meta__.source,
id: attributes[:id],
attributes: attributes,
links: %{ "self": "something" },
relationships: relationships,
included: included
}
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment