Skip to content

Commit 61fd794

Browse files
authored
Verify fields given to @derive (michalmuskala#123)
1 parent 2d40876 commit 61fd794

File tree

2 files changed

+49
-3
lines changed

2 files changed

+49
-3
lines changed

lib/encoder.ex

Lines changed: 23 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -135,15 +135,35 @@ defimpl Jason.Encoder, for: Any do
135135
end
136136

137137
defp fields_to_encode(struct, opts) do
138+
fields = Map.keys(struct)
139+
138140
cond do
139141
only = Keyword.get(opts, :only) ->
140-
only
142+
case only -- fields do
143+
[] ->
144+
only
145+
146+
error_keys ->
147+
raise ArgumentError,
148+
"`:only` specified keys (#{inspect(error_keys)}) that are not defined in defstruct: " <>
149+
"#{inspect(fields -- [:__struct__])}"
150+
151+
end
141152

142153
except = Keyword.get(opts, :except) ->
143-
Map.keys(struct) -- [:__struct__ | except]
154+
case except -- fields do
155+
[] ->
156+
fields -- [:__struct__ | except]
157+
158+
error_keys ->
159+
raise ArgumentError,
160+
"`:except` specified keys (#{inspect(error_keys)}) that are not defined in defstruct: " <>
161+
"#{inspect(fields -- [:__struct__])}"
162+
163+
end
144164

145165
true ->
146-
Map.keys(struct) -- [:__struct__]
166+
fields -- [:__struct__]
147167
end
148168
end
149169
end

test/encode_test.exs

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

137+
test "@derive validate `except:`" do
138+
message = "`:except` specified keys ([:invalid]) that are not defined in defstruct: [:name]"
139+
140+
assert_raise ArgumentError, message, fn ->
141+
Code.eval_string("""
142+
defmodule InvalidExceptField do
143+
@derive {Jason.Encoder, except: [:invalid]}
144+
defstruct name: ""
145+
end
146+
""")
147+
end
148+
end
149+
150+
test "@derive validate `only:`" do
151+
message = "`:only` specified keys ([:invalid]) that are not defined in defstruct: [:name]"
152+
153+
assert_raise ArgumentError, message, fn ->
154+
Code.eval_string("""
155+
defmodule InvalidOnlyField do
156+
@derive {Jason.Encoder, only: [:invalid]}
157+
defstruct name: ""
158+
end
159+
""")
160+
end
161+
end
162+
137163
defmodule KeywordTester do
138164
defstruct [:baz, :foo, :quux]
139165
end

0 commit comments

Comments
 (0)