Skip to content

Commit cb1f26a

Browse files
isaac-rstormichalmuskala
authored andcommitted
allows for encoding keyword lists (michalmuskala#62)
added a method to do encodings directly through keyword lists
1 parent 3fb312e commit cb1f26a

File tree

2 files changed

+52
-16
lines changed

2 files changed

+52
-16
lines changed

lib/encode.ex

Lines changed: 33 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -150,19 +150,30 @@ defmodule Jason.Encode do
150150
| list_loop(tail, escape, encode_map)]
151151
end
152152

153+
@spec keyword(keyword, opts) :: iodata
154+
def keyword(list, {escape, encode_map}) do
155+
encode_map.(list, escape, encode_map)
156+
end
157+
153158
@spec map(map, opts) :: iodata
154159
def map(value, {escape, encode_map}) do
155160
encode_map.(value, escape, encode_map)
156161
end
157162

163+
defp map_naive([], _escape, _encode_map) do
164+
"{}"
165+
end
166+
167+
defp map_naive([{key, value} | tail], escape, encode_map) do
168+
["{\"", key(key, escape), "\":",
169+
value(value, escape, encode_map)
170+
| map_naive_loop(tail, escape, encode_map)]
171+
end
172+
158173
defp map_naive(value, escape, encode_map) do
159-
case Map.to_list(value) do
160-
[] -> "{}"
161-
[{key, value} | tail] ->
162-
["{\"", key(key, escape), "\":",
163-
value(value, escape, encode_map)
164-
| map_naive_loop(tail, escape, encode_map)]
165-
end
174+
value
175+
|> Map.to_list
176+
|> map_naive(escape, encode_map)
166177
end
167178

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

189+
defp map_strict([], _escape, _encode_map) do
190+
"{}"
191+
end
192+
193+
defp map_strict([{key, value} | tail], escape, encode_map) do
194+
key = IO.iodata_to_binary(key(key, escape))
195+
visited = %{key => []}
196+
["{\"", key, "\":",
197+
value(value, escape, encode_map)
198+
| map_strict_loop(tail, escape, encode_map, visited)]
199+
end
200+
178201
defp map_strict(value, escape, encode_map) do
179-
case Map.to_list(value) do
180-
[] -> "{}"
181-
[{key, value} | tail] ->
182-
key = IO.iodata_to_binary(key(key, escape))
183-
visited = %{key => []}
184-
["{\"", key, "\":",
185-
value(value, escape, encode_map)
186-
| map_strict_loop(tail, escape, encode_map, visited)]
187-
end
202+
value
203+
|> Map.to_list
204+
|> map_strict(escape, encode_map)
188205
end
189206

190207
defp map_strict_loop([], _encode_map, _escape, _visited) do

test/encode_test.exs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,24 @@ defmodule Jason.EncoderTest do
133133
assert to_json(derived_using_except) == ~s({"size":10})
134134
end
135135

136+
defmodule KeywordTester do
137+
defstruct [:baz, :foo, :quux]
138+
end
139+
140+
defimpl Jason.Encoder, for: [KeywordTester] do
141+
def encode(struct, opts) do
142+
struct
143+
|> Map.from_struct
144+
|> Enum.map(&(&1))
145+
|> Jason.Encode.keyword(opts)
146+
end
147+
end
148+
149+
test "using keyword list encoding" do
150+
t = %KeywordTester{baz: :bar, foo: "bag", quux: 42}
151+
assert to_json(t) == ~s({"baz":"bar","foo":"bag","quux":42})
152+
end
153+
136154
test "EncodeError" do
137155
assert_raise Protocol.UndefinedError, fn ->
138156
to_json(self())
@@ -162,4 +180,5 @@ defmodule Jason.EncoderTest do
162180
defp to_json(value, opts \\ []) do
163181
Jason.encode!(value, opts)
164182
end
183+
165184
end

0 commit comments

Comments
 (0)