Skip to content
Open
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
18 changes: 17 additions & 1 deletion lib/encoder.ex
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ defprotocol Jason.Encoder do

* `:only` - encodes only values of specified keys.
* `:except` - encodes all struct fields except specified keys.
* `:sort_keys` - sorts the keys, optionally with a custom function.

By default all keys except the `:__struct__` key are encoded.

Expand Down Expand Up @@ -51,6 +52,13 @@ defprotocol Jason.Encoder do
The actually generated implementations are more efficient computing some data
during compilation similar to the macros from the `Jason.Helpers` module.

## Sorting keys

You can also sort the keys in the output JSON, either according to Erlang's
term ordering with `@derive {Jason.Encoder, sort_keys: true}` or using a custom
sort function (as passed to `Enum.sort/2`) e.g.
`@derive {Jason.Encoder, sort_keys: &(&1>=&2)}`

## Explicit implementation

If you wish to implement the protocol fully yourself, it is advised to
Expand Down Expand Up @@ -138,7 +146,15 @@ defimpl Jason.Encoder, for: Any do
end

defp fields_to_encode(struct, opts) do
fields = Map.keys(struct)
fields = case Keyword.get(opts, :sort_keys) do
true ->
Map.keys(struct) |> Enum.sort()
sort_fn when is_function(sort_fn, 2) ->
Map.keys(struct)
|> Enum.sort(sort_fn)
nil ->
Map.keys(struct)
end

cond do
only = Keyword.get(opts, :only) ->
Expand Down
18 changes: 18 additions & 0 deletions test/encode_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,18 @@ defmodule Jason.EncoderTest do
defstruct name: "", size: 0
end

defmodule DerivedUsingSortKeys do
@derive {Encoder, sort_keys: true}
defstruct a: 1, b: "", c: nil, d: 4
end


defmodule DerivedUsingCustomSortKeys do
@derive {Encoder, sort_keys: &(&1>=&2)}
defstruct a: 1, b: "", c: nil, d: 4
end


defmodule DerivedWeirdKey do
@derive Encoder
defstruct [:_]
Expand All @@ -160,6 +172,12 @@ defmodule Jason.EncoderTest do
derived_using_except = %DerivedUsingExcept{name: "derived using :except", size: 10}
assert to_json(derived_using_except) == ~s({"size":10})

derived_using_sort_keys = %DerivedUsingSortKeys{}
assert to_json(derived_using_sort_keys) == ~s({"a":1,"b":"","c":null,"d":4})

derived_using_custom_sort_keys = %DerivedUsingCustomSortKeys{}
assert to_json(derived_using_custom_sort_keys) == ~s({"d":4,"c":null,"b":"","a":1})

derived_weird_key = %DerivedWeirdKey{}
assert to_json(derived_weird_key) == ~s({"_":null})
end
Expand Down