     end
   end
 
-  def decodable?(env, opts), do: decodable_body?(env) && decodable_content_type?(env, opts)
+  defp decodable?(env, opts), do: decodable_body?(env) && decodable_content_type?(env, opts)
 
-  def decodable_body?(env) do
+  defp decodable_body?(env) do
     (is_binary(env.body)  && env.body != "") ||
     (is_list(env.body)    && env.body != [])
   end
 
-  def decodable_content_type?(env, opts) do
+  defp decodable_content_type?(env, opts) do
     case env.headers["content-type"] do
       nil           -> false
       content_type  -> Enum.any?(content_types(opts), &String.starts_with?(content_type, &1))
     end
   end
 
-  def content_types(opts), do: @default_content_types ++ Keyword.get(opts, :decode_content_types, [])
+  defp content_types(opts), do: @default_content_types ++ Keyword.get(opts, :decode_content_types, [])
 
   defp process(data, op, opts) do
     with {:ok, value} <- do_process(data, op, opts) do

    Stream.map body, fn item -> encode_body(item, opts) <> "\n" end
  end

  def encodable?(%{body: nil}),                 do: false
  def encodable?(%{body: %Tesla.Multipart{}}),  do: false
  def encodable?(_),                            do: true

  def decode(env, opts) do
    if decodable?(env, opts) do
      Map.update!(env, :body, &process(&1, :decode, opts))

defmodule Tesla.Middleware.JSON do
  @behaviour Tesla.Middleware

  @moduledoc """
  Encode requests and decode responses as JSON.

  This middleware requires [poison](https://hex.pm/packages/poison) (or other engine) as dependency.

  Remember to add `{:poison, ">= 1.0"}` to dependencies (and `:poison` to applications in `mix.exs`)
  Also, you need to recompile tesla after adding `:poison` dependency:

  ```
  mix deps.clean tesla
  mix deps.compile tesla
  ```


  ### Example usage
  ```
  defmodule MyClient do
    use Tesla

    plug Tesla.Middleware.JSON # use poison engine
    # or
    plug Tesla.Middleware.JSON, engine: JSX, engine_opts: [strict: [:comments]]
    # or
    plug Tesla.Middleware.JSON, decode: &JSX.decode/1, encode: &JSX.encode/1
  end
  ```

  ### Options
  - `:decode` - decoding function
  - `:encode` - encoding function
  - `:engine` - encode/decode engine, e.g `Poison` or `JSX`  (defaults to Poison)
  - `:engine_opts` - optional engine options
  - `:decode_content_types` - list of additional decodable content-types
  """


  # NOTE: text/javascript added to support Facebook Graph API.
  #       see https://github.com/teamon/tesla/pull/13
  @default_content_types ["application/json", "text/javascript"]
  @default_engine Poison

  def call(env, next, opts) do
    opts = opts || []

