ScoreVision / ja_spex

A bridge between OpenApiSpex and JaSerializer

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

JaSpex

A bridge between OpenApiSpex and JaSerializer

Installation

Add ja_spex to your list of dependencies in mix.exs:

def deps do
  [
    {:ja_spex, git: "https://github.com/ReelCoaches/ja_spex.git", tag: "0.1.0"}
  ]
end

Setup

ApiSpec (OpenApiSpex)

Setup your ApiSpec module as defined in the Generate Spec section of the OpenApiSpex docs.

Schemas (OpenApiSpex)

OpenApiSpex Schemas can be deserialized by JaSerializer when you use JaSpex:

```elixir
defmodule UserSchema do
  require OpenApiSpex
  use JaSpex

  OpenApiSpex.schema(...)
end
```

Controller

Add plug JaSpex to cast, validate, and deserialize your requests:

defmodule MyWeb.ImageController do
  use Phoenix.Controller

  plug(JaSpex)

  # ...
end

Additional Considerations

DateTime properties

If you specify a property with a :date-time format in your schema, OpenApiSpex will cast its value to a DateTime struct. If you would like the values to be returned in another format, you can implement the JaSerializer.ParamParser protocol for DateTime:

defimpl JaSerializer.ParamParser, for: DateTime do
  def parse(%DateTime{} = datetime), do: DateTime.to_iso8601(datetime)
end

Examples

Phoenix.Router

  pipeline :api do
    plug(:accepts, ["json-api"])
    plug(OpenApiSpex.Plug.PutApiSpec, module: MyWeb.ApiSpec)
    plug(JaSerializer.ContentTypeNegotiation)
  end

Phoenix.Controller

defmodule MyWeb.ImageController do
  use Phoenix.Controller
  # Defines operation callbacks
  use JaSpex.Controller

  # Validates and deserializes request params
  plug JaSpex

  def show_operation do
    import Operation
    alias MyWeb.Schemas.ImageResponse

    %Operation{
      tags: ["images"],
      summary: "Show image",
      description: "Returns information about an image by its ID",
      operationId: "ImageController.show",
      parameters: [
        parameter(:id, :path, :integer, "Image ID", example: 123)
      ],
      responses: %{
        200 => response("Image", JaSpex.jsonapi(), ImageResponse)
      }
    }
  end

  def show(conn, %{"id" => image_id}) do
    with {:ok, user} <- Users.find_by_id(user_id) do
        conn |> render("show.json-api", data: user)
    end
  end
end

Schemas

defmodule MyWeb.Schemas do
  require OpenApiSpex
  alias OpenApiSpex.Schema

  defmodule Image do
    use JaSpex, no_parse_fields: [:exif]

    OpenApiSpex.schema(%{
      title: "Image",
      description: "An image file",
      type: :object,
      properties: %{
        name: %Schema{
          type: :string,
          description: "Image filename"
        },
        width: %Schema{
          type: :integer,
          description: "Image width in pixels"
        },
        height: %Schema{
          type: :integer,
          description: "Image height in pixels"
        },
        takenAt: %Schema{
          type: :string,
          description: "The creation datetime of the image",
          format: :"date-time"
        },
        exif: %Schema{
          type: :object,
          additionalProperties: %Schema{
            type: :string
          }
        }
      },
      required: [:name, :width, :height],
      additionalProperties: false,
      example: %{
        "name" => "foo_thumbnail.jpg",
        "width" => 64,
        "height" => 64,
        "takenAt" => "2017-09-13T10:11:12Z",
        "exif" => %{
          "model" => "Canon 5D",
          "creationTimestamp" => "2017-09-13T10:11:12Z"
        }
      }
    })
  end

  defmodule ImageResponse do
    use JaSpex

    OpenApiShema.schema(%{
      title: "ImageResponse",
      description: "An image response object in JSON:API format",
      type: :object,
      properties: %{
        data: %Schema{
          type: :object,
          properties: %{
            id: %Schema{
              type: :integer,
              example: 12345
            },
            type: %Schema{
              type: :string,
              example: "images"
            },
            attributes: Image
          },
          required: [:id, :type, :attributes]
        },
        links: %Schema{
          type: :object,
          properties: %{
            self: %Schema{
              type: :string,
              format: :uri,
              example: "https://localhost:4000/images/12345"
            }
          }
        }
      },
      example: %{
        "data" => %{
          "type" => "images",
          "attributes" => Image.schema().example,
          "id" => 123456
        }
      }
    })
  end
end

About

A bridge between OpenApiSpex and JaSerializer

License:Apache License 2.0


Languages

Language:Elixir 100.0%