Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,7 @@ config :jsonapi,
namespace: "/api",
field_transformation: :underscore,
remove_links: false,
serialize_nil_relationships: false,
json_library: Jason,
paginator: nil
```
Expand All @@ -219,6 +220,10 @@ config :jsonapi,
`:camelize_shallow` or `:dasherize_shallow`.
- **remove_links**. `links` data can optionally be removed from the payload via
setting the configuration above to `true`. Defaults to `false`.
- **serialize_nil_relationships**. By default, relationships on a resource that
are `nil` will be omitted during serialization. Setting this to `true` will
serialize these relationships, provided they are loaded on the resource.
Defaults to `false`.
- **json_library**. Defaults to [Jason](https://hex.pm/packages/jason).
- **paginator**. Module implementing pagination links generation. Defaults to `nil`.

Expand Down
5 changes: 4 additions & 1 deletion lib/jsonapi/serializer.ex
Original file line number Diff line number Diff line change
Expand Up @@ -270,7 +270,7 @@ defmodule JSONAPI.Serializer do
|> Enum.uniq()
end

defp assoc_loaded?(nil), do: false
defp assoc_loaded?(nil), do: serialize_nil_relationships?()
defp assoc_loaded?(%{__struct__: Ecto.Association.NotLoaded}), do: false
defp assoc_loaded?(_association), do: true

Expand Down Expand Up @@ -304,6 +304,9 @@ defmodule JSONAPI.Serializer do

defp remove_links?, do: Application.get_env(:jsonapi, :remove_links, false)

@spec serialize_nil_relationships? :: boolean()
defp serialize_nil_relationships?, do: Application.get_env(:jsonapi, :serialize_nil_relationships, false)

defp transform_fields(fields) do
case Utils.String.field_transformation() do
:camelize -> Utils.String.expand_fields(fields, &Utils.String.camelize/1)
Expand Down
91 changes: 90 additions & 1 deletion test/jsonapi/serializer_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -202,6 +202,9 @@ defmodule JSONAPI.SerializerTest do

%PolymorphicDataTwo{} ->
"polymorphic_data_one"

nil ->
nil
end
end

Expand All @@ -221,6 +224,7 @@ defmodule JSONAPI.SerializerTest do

on_exit(fn ->
Application.delete_env(:jsonapi, :field_transformation)
Application.delete_env(:jsonapi, :serialize_nil_relationships)
end)

{:ok, []}
Expand Down Expand Up @@ -360,7 +364,7 @@ defmodule JSONAPI.SerializerTest do
assert Enum.count(encoded[:included]) == 1
end

test "serialize handles a nil relationship" do
test "serialize excludes a nil relationship by default" do
data = %{
id: 1,
text: "Hello",
Expand All @@ -380,11 +384,96 @@ defmodule JSONAPI.SerializerTest do
assert attributes[:body] == data[:body]

assert encoded_data[:links][:self] == PostView.url_for(data, nil)
refute Map.has_key?(encoded_data[:relationships], :best_comments)
assert map_size(encoded_data[:relationships]) == 1

assert Enum.count(encoded[:included]) == 1
end

test "serialize excludes unloaded ecto association by default" do
data = %{
id: 1,
text: "Hello",
body: "Hello world",
author: %{id: 2, username: "jason"},
best_comments: %{__struct__: Ecto.Association.NotLoaded}
}

encoded = Serializer.serialize(PostView, data, nil)

encoded_data = encoded[:data]
assert encoded_data[:id] == PostView.id(data)
assert encoded_data[:type] == PostView.type()

attributes = encoded_data[:attributes]
assert attributes[:text] == data[:text]
assert attributes[:body] == data[:body]

assert encoded_data[:links][:self] == PostView.url_for(data, nil)
refute Map.has_key?(encoded_data[:relationships], :best_comments)
assert map_size(encoded_data[:relationships]) == 1

assert Enum.count(encoded[:included]) == 1
end

test "serialize includes nil relationships when configured" do
Application.put_env(:jsonapi, :serialize_nil_relationships, true)

data = %{
id: 1,
text: "Hello",
body: "Hello world",
author: %{id: 2, username: "jason"},
best_comments: nil
}

encoded = Serializer.serialize(PostView, data, nil)

encoded_data = encoded[:data]
assert encoded_data[:id] == PostView.id(data)
assert encoded_data[:type] == PostView.type()

attributes = encoded_data[:attributes]
assert attributes[:text] == data[:text]
assert attributes[:body] == data[:body]

assert encoded_data[:links][:self] == PostView.url_for(data, nil)
assert map_size(encoded_data[:relationships]) == 3
assert encoded_data[:relationships][:best_comments][:data] == nil
assert encoded_data[:relationships][:polymorphics][:data] == nil

assert Enum.count(encoded[:included]) == 1
end

test "serialize excludes unloaded ecto association when serialize nil relationships configured" do
Application.put_env(:jsonapi, :serialize_nil_relationships, true)

data = %{
id: 1,
text: "Hello",
body: "Hello world",
author: %{id: 2, username: "jason"},
best_comments: %{__struct__: Ecto.Association.NotLoaded}
}

encoded = Serializer.serialize(PostView, data, nil)

encoded_data = encoded[:data]
assert encoded_data[:id] == PostView.id(data)
assert encoded_data[:type] == PostView.type()

attributes = encoded_data[:attributes]
assert attributes[:text] == data[:text]
assert attributes[:body] == data[:body]

assert encoded_data[:links][:self] == PostView.url_for(data, nil)
assert map_size(encoded_data[:relationships]) == 2
assert Map.has_key?(encoded_data[:relationships], :polymorphics)
refute Map.has_key?(encoded_data[:relationships], :best_comments)

assert Enum.count(encoded[:included]) == 1
end

test "serialize handles a relationship self link on a show request" do
data = %{
id: 1,
Expand Down
Loading