defmodule JSONRPC2.Spec.Response do @moduledoc """ Helper functions to work with respoinse. """ alias JSONRPC2.Spec.Error alias JSONRPC2.Spec.Result @type raw_resp :: map() | [map()] @type one_resp :: Error.t() | Result.t() @type many_resp :: [one_resp()] @type resp :: one_resp() | many_resp() defdelegate error(id, code), to: Error, as: :new defdelegate error(id, code, message_or_data), to: Error, as: :new defdelegate error(id, code, message, data), to: Error, as: :new defdelegate result(id, value), to: Result, as: :new @spec parse(String.t()) :: resp() def parse("") do [] end def parse(response) when is_binary(response) do case JSON.decode(response) do {:ok, data} -> build(data) _ -> error(nil, -32700, "Invalid JSON Response", response) end end @spec build(raw_resp()) :: resp() def build(responses) when is_list(responses) do Enum.map(responses, &(build(&1))) end def build(%{"id" => id, "result" => result, "jsonrpc" => "2.0"}) do result(id, result) end def build(%{"result" => result, "jsonrpc" => "2.0"}) do result(nil, result) end def build(%{"id" => id, "error" => error, "jsonrpc" => "2.0"}) do error(id, error["code"], error["message"], error["data"]) end def build(%{"error" => error, "jsonrpc" => "2.0"}) do error(nil, error["code"], error["message"], data: error["data"]) end def build(response) do error(response["id"], -32600, "Invalid Response", response) end end