Skip to content

Commit

Permalink
allows for encoding keyword lists (#62)
Browse files Browse the repository at this point in the history
added a method to do encodings directly through keyword lists
  • Loading branch information
isaac-rstor authored and michalmuskala committed Nov 14, 2018
1 parent 3fb312e commit cb1f26a
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 16 deletions.
49 changes: 33 additions & 16 deletions lib/encode.ex
Original file line number Diff line number Diff line change
Expand Up @@ -150,19 +150,30 @@ defmodule Jason.Encode do
| list_loop(tail, escape, encode_map)]
end

@spec keyword(keyword, opts) :: iodata
def keyword(list, {escape, encode_map}) do
encode_map.(list, escape, encode_map)
end

@spec map(map, opts) :: iodata
def map(value, {escape, encode_map}) do
encode_map.(value, escape, encode_map)
end

defp map_naive([], _escape, _encode_map) do
"{}"
end

defp map_naive([{key, value} | tail], escape, encode_map) do
["{\"", key(key, escape), "\":",
value(value, escape, encode_map)
| map_naive_loop(tail, escape, encode_map)]
end

defp map_naive(value, escape, encode_map) do
case Map.to_list(value) do
[] -> "{}"
[{key, value} | tail] ->
["{\"", key(key, escape), "\":",
value(value, escape, encode_map)
| map_naive_loop(tail, escape, encode_map)]
end
value
|> Map.to_list
|> map_naive(escape, encode_map)
end

defp map_naive_loop([], _escape, _encode_map) do
Expand All @@ -175,16 +186,22 @@ defmodule Jason.Encode do
| map_naive_loop(tail, escape, encode_map)]
end

defp map_strict([], _escape, _encode_map) do
"{}"
end

defp map_strict([{key, value} | tail], escape, encode_map) do
key = IO.iodata_to_binary(key(key, escape))
visited = %{key => []}
["{\"", key, "\":",
value(value, escape, encode_map)
| map_strict_loop(tail, escape, encode_map, visited)]
end

defp map_strict(value, escape, encode_map) do
case Map.to_list(value) do
[] -> "{}"
[{key, value} | tail] ->
key = IO.iodata_to_binary(key(key, escape))
visited = %{key => []}
["{\"", key, "\":",
value(value, escape, encode_map)
| map_strict_loop(tail, escape, encode_map, visited)]
end
value
|> Map.to_list
|> map_strict(escape, encode_map)
end

defp map_strict_loop([], _encode_map, _escape, _visited) do
Expand Down
19 changes: 19 additions & 0 deletions test/encode_test.exs
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,24 @@ defmodule Jason.EncoderTest do
assert to_json(derived_using_except) == ~s({"size":10})
end

defmodule KeywordTester do
defstruct [:baz, :foo, :quux]
end

defimpl Jason.Encoder, for: [KeywordTester] do
def encode(struct, opts) do
struct
|> Map.from_struct
|> Enum.map(&(&1))
|> Jason.Encode.keyword(opts)
end
end

test "using keyword list encoding" do
t = %KeywordTester{baz: :bar, foo: "bag", quux: 42}
assert to_json(t) == ~s({"baz":"bar","foo":"bag","quux":42})
end

test "EncodeError" do
assert_raise Protocol.UndefinedError, fn ->
to_json(self())
Expand Down Expand Up @@ -162,4 +180,5 @@ defmodule Jason.EncoderTest do
defp to_json(value, opts \\ []) do
Jason.encode!(value, opts)
end

end

0 comments on commit cb1f26a

Please sign in to comment.