diff --git a/lib/protox/define_message.ex b/lib/protox/define_message.ex index 0f262bb..df98fa8 100644 --- a/lib/protox/define_message.ex +++ b/lib/protox/define_message.ex @@ -1,13 +1,10 @@ defmodule Protox.DefineMessage do @moduledoc false - @default_json_library Jason - alias Protox.Field def define(messages, opts \\ []) do keep_unknown_fields = Keyword.get(opts, :keep_unknown_fields, true) - json_library = Keyword.get(opts, :json_library, @default_json_library) for msg = %Protox.Message{} <- messages do fields = Enum.sort(msg.fields, &(&1.tag < &2.tag)) @@ -19,7 +16,7 @@ defmodule Protox.DefineMessage do unknown_fields_funs = make_unknown_fields_funs(unknown_fields, keep_unknown_fields) required_fields_fun = make_required_fields_fun(required_fields) fields_access_funs = make_fields_access_funs(fields) - json_funs = make_json_funs(msg.name, json_library) + json_funs = make_json_funs(msg.name, Protox.JsonLibrary.get_wrapper(opts)) default_fun = make_default_funs(fields) syntax_fun = make_syntax_fun(msg.syntax) file_options_fun = make_file_options_fun(msg) @@ -96,9 +93,31 @@ defmodule Protox.DefineMessage do end end - defp make_json_funs(msg_name, json_library) do - json_library_wrapper = Protox.JsonLibrary.get_wrapper(json_library) + defp make_json_funs(_msg_name, _json_library_wrapper = nil) do + quote do + @spec json_decode(iodata()) :: {:error, any()} + def json_decode(_input) do + {:error, Protox.JsonLibraryError.new()} + end + + @spec json_decode!(iodata()) :: no_return() + def json_decode!(_input) do + raise Protox.JsonLibraryError.new() + end + + @spec json_encode(struct()) :: {:error, any()} + def json_encode(_msg) do + {:error, Protox.JsonLibraryError.new()} + end + + @spec json_encode!(struct()) :: no_return() + def json_encode!(_msg) do + raise Protox.JsonLibraryError.new() + end + end + end + defp make_json_funs(msg_name, json_library_wrapper) do quote do @spec json_decode(iodata()) :: {:ok, struct()} | {:error, any()} def json_decode(input) do diff --git a/lib/protox/jason.ex b/lib/protox/jason.ex index 3634a2f..9fb6e7c 100644 --- a/lib/protox/jason.ex +++ b/lib/protox/jason.ex @@ -1,24 +1,27 @@ defmodule Protox.Jason do @moduledoc false - @behaviour Protox.JsonLibrary - @impl true - def decode!(iodata) do - try do - Jason.decode!(iodata) - rescue - e in [Jason.DecodeError, Protocol.UndefinedError] -> - reraise Protox.JsonDecodingError.new(Exception.message(e)), __STACKTRACE__ + if Code.ensure_loaded?(Jason) do + @behaviour Protox.JsonLibrary + + @impl true + def decode!(iodata) do + try do + Jason.decode!(iodata) + rescue + e in [Jason.DecodeError, Protocol.UndefinedError] -> + reraise Protox.JsonDecodingError.new(Exception.message(e)), __STACKTRACE__ + end end - end - @impl true - def encode!(term) do - try do - Jason.encode_to_iodata!(term) - rescue - e in Jason.EncodeError -> - reraise Protox.JsonEncodingError.new(Exception.message(e)), __STACKTRACE__ + @impl true + def encode!(term) do + try do + Jason.encode_to_iodata!(term) + rescue + e in Jason.EncodeError -> + reraise Protox.JsonEncodingError.new(Exception.message(e)), __STACKTRACE__ + end end end end diff --git a/lib/protox/json_library.ex b/lib/protox/json_library.ex index cd6f4cd..6ac7c7e 100644 --- a/lib/protox/json_library.ex +++ b/lib/protox/json_library.ex @@ -3,6 +3,8 @@ defmodule Protox.JsonLibrary do The behaviour to implement when wrapping a JSON library. """ + @default_json_library Jason + @doc """ Should wrap any exception of the underlying library in Protox.JsonDecodingError. """ @@ -14,11 +16,13 @@ defmodule Protox.JsonLibrary do @callback encode!(term()) :: iodata() | no_return() @doc false - def get_wrapper(json_library) do + def get_wrapper(opts) do + json_library = Keyword.get(opts, :json_library, @default_json_library) + if Code.ensure_loaded?(json_library) do Module.concat(Protox, json_library) else - raise Protox.JsonLibraryError.new() + nil end end end diff --git a/lib/protox/poison.ex b/lib/protox/poison.ex index d4fc3e6..3fb52e0 100644 --- a/lib/protox/poison.ex +++ b/lib/protox/poison.ex @@ -1,24 +1,27 @@ defmodule Protox.Poison do @moduledoc false - @behaviour Protox.JsonLibrary - @impl true - def decode!(iodata) do - try do - Poison.decode!(iodata) - rescue - e in [Poison.DecodeError, Poison.ParseError] -> - reraise Protox.JsonDecodingError.new(Exception.message(e)), __STACKTRACE__ + if Code.ensure_loaded?(Poison) do + @behaviour Protox.JsonLibrary + + @impl true + def decode!(iodata) do + try do + Poison.decode!(iodata) + rescue + e in [Poison.DecodeError, Poison.ParseError] -> + reraise Protox.JsonDecodingError.new(Exception.message(e)), __STACKTRACE__ + end end - end - @impl true - def encode!(term) do - try do - Poison.encode!(term) - rescue - e in Poison.EncodeError -> - reraise Protox.JsonEncodingError.new(Exception.message(e)), __STACKTRACE__ + @impl true + def encode!(term) do + try do + Poison.encode!(term) + rescue + e in Poison.EncodeError -> + reraise Protox.JsonEncodingError.new(Exception.message(e)), __STACKTRACE__ + end end end end