Skip to content

Commit ad2beb2

Browse files
authored
feat: add function serialization support (#9)
- Added support for function serialization in `ensure_json_serializable/1`. - Functions are now converted to JSON by capturing their module, name, and arity. - Anonymous functions are labeled as "anonymous function" in the output for clarity.
1 parent 9e2b91c commit ad2beb2

File tree

2 files changed

+61
-4
lines changed

2 files changed

+61
-4
lines changed

lib/error_message/serializer.ex

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,11 @@ defmodule ErrorMessage.Serializer do
1313
end
1414

1515
def to_jsonable_map(%ErrorMessage{code: code, message: message, details: details}) do
16-
if Logger.metadata[:request_id] do
16+
if Logger.metadata()[:request_id] do
1717
%{
1818
code: code,
1919
message: message,
20-
request_id: Logger.metadata[:request_id],
20+
request_id: Logger.metadata()[:request_id],
2121
details: ensure_json_serializable(details)
2222
}
2323
else
@@ -65,7 +65,7 @@ defmodule ErrorMessage.Serializer do
6565

6666
defp ensure_json_serializable(%struct{} = struct_data) do
6767
%{
68-
struct: struct |> Kernel.to_string |> String.replace("Elixir.", ""),
68+
struct: struct |> Kernel.to_string() |> String.replace("Elixir.", ""),
6969
data: struct_data |> Map.from_struct() |> ensure_json_serializable
7070
}
7171
end
@@ -77,7 +77,19 @@ defmodule ErrorMessage.Serializer do
7777
end
7878

7979
defp ensure_json_serializable(details) when is_tuple(details) do
80-
details |> Tuple.to_list |> ensure_json_serializable
80+
details |> Tuple.to_list() |> ensure_json_serializable
81+
end
82+
83+
defp ensure_json_serializable(fun) when is_function(fun) do
84+
{:module, module} = :erlang.fun_info(fun, :module)
85+
{:name, function_name} = :erlang.fun_info(fun, :name)
86+
{:arity, arity} = :erlang.fun_info(fun, :arity)
87+
88+
%{
89+
module: Atom.to_string(module),
90+
function: Atom.to_string(function_name),
91+
arity: arity
92+
}
8193
end
8294

8395
defp ensure_json_serializable(value) do
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
defmodule ErrorMessage.SerializerTest do
2+
use ExUnit.Case
3+
4+
describe "&to_jsonable_map/1" do
5+
test "serializes anonymous function correctly" do
6+
anon_fun = fn x -> x + 1 end
7+
error_msg = ErrorMessage.not_found("anonymous function serialization", anon_fun)
8+
9+
serialized = ErrorMessage.Serializer.to_jsonable_map(error_msg)
10+
11+
assert serialized.details === %{
12+
module: "Elixir.ErrorMessage.SerializerTest",
13+
function:
14+
"-test &to_jsonable_map/1 serializes anonymous function correctly/1-fun-0-",
15+
arity: 1
16+
}
17+
end
18+
19+
test "serializes named function correctly" do
20+
named_fun = &String.length/1
21+
error_msg = ErrorMessage.not_found("named function serialization", named_fun)
22+
23+
serialized = ErrorMessage.Serializer.to_jsonable_map(error_msg)
24+
25+
assert serialized.details === %{
26+
module: "Elixir.String",
27+
function: "length",
28+
arity: 1
29+
}
30+
end
31+
32+
test "serializes Erlang function correctly" do
33+
erlang_fun = &:erlang.self/0
34+
error_msg = ErrorMessage.not_found("Erlang function serialization", erlang_fun)
35+
36+
serialized = ErrorMessage.Serializer.to_jsonable_map(error_msg)
37+
38+
assert serialized.details === %{
39+
module: "erlang",
40+
function: "self",
41+
arity: 0
42+
}
43+
end
44+
end
45+
end

0 commit comments

Comments
 (0)