Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to render a JSON file with the Phoenix framework?

Instead of fetching data from a database, I want to use as data a manually written JSON file. Suppose my data is this:

[
    { "id": 1, "name": "Alice", "email": "[email protected]" },
    { "id": 2, "name": "Bob", "email": "bob@example" },
    { "id": 3, "name": "Charles", "email": "[email protected]"}
]

and it's written in a file called MOCK_DATA.json. What should I do to render this file when I access the localhost:port/api/v1/users url? How about the localhost:port/api/v1/users/1 url to show { "id": 1, "name": "Alice", "email": "[email protected]" }?

like image 625
Marcus Vinícius Monteiro Avatar asked Jan 26 '16 21:01

Marcus Vinícius Monteiro


2 Answers

Here is a basic working example...

Step 1: Create the phoenix app

eg, exjson for ExampleJson or whatever name your like

mix phoenix.new exjson --no-ecto --no-brunch --no-html
Step 2: Set up the router

Add this scope to the web/router.ex file

  scope "/api/v1", Exjson do
    pipe_through :api
    resources "/users", UserController
  end
Step 3: Put the mock data somewhere accessible to the app
priv/data/MOCK_DATA.json
Step 4: Set up the UsersController

Think of the Users Controller as having a number of actions (functions) where the conn struct is fed into from your phoenix endpoint along with any parameters

defmodule Exjson.UserController do
  use Exjson.Web, :controller

  # GET http://localhost:4000/api/v1/users/
  def index(conn, _params) do
    users = File.read!(file) |> Poison.decode!()
    render conn, users: users
  end

  # GET http://localhost:4000/api/v1/users/1
  def show(conn, params) do
    users = File.read!(file) |> Poison.decode!()
    render conn, user: users |> Enum.find(&(&1["id"] === String.to_integer(params["id"])))
  end

  defp file() do
    Path.join(:code.priv_dir(:exjson), "data/MOCK_DATA.json")
  end

end
Step 5: Set up the UsersView

You can also think of the Users View as having functions that will render the data received from the Controller in the appropriate way. In this case, you are using json data so phoenix has some built in functions to help with that.

defmodule Exjson.UserView do
  use Exjson.Web, :view

  def render("index.json", %{users: users}) do
    render_many(users, __MODULE__, "user.json")
  end

  def render("show.json", %{user: user}) do
    render_one(user, __MODULE__, "user.json")
  end

  def render("user.json", %{user: user}) do
    %{
      id: user["id"],
      name: user["name"],
      email: user["email"]
    }
  end

end
like image 117
stephen_m Avatar answered Nov 15 '22 08:11

stephen_m


To give you some real code to get started, this is the simplest thing I can think of:

defmodule MyApp.UserController do
  @mock_data (
    Application.app_dir(:my_app, "priv/mock_data/users.json")
    |> File.read!
    |> Poison.decode!
  )

  def index(conn, _params) do
    conn
    |> put_status(:ok)
    |> json(@mock_data)
  end
end

Then just save your fake data in priv/mock_data/users.json inside your project. There might be typos in there, but you get the basic idea...

like image 24
Patrick Oscity Avatar answered Nov 15 '22 10:11

Patrick Oscity