How to render a JSON file using the phoenix framework?

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

[ { "id": 1, "name": "Alice", "email": " alice@example.com " }, { "id": 2, "name": "Bob", "email": " bob@example " }, { "id": 3, "name": "Charles", "email": " charles@example.com "} ] 

and it is written in a file called MOCK_DATA.json . What should I do to display this file when I access the localhost:port/api/v1/users url localhost:port/api/v1/users ? What about the localhost:port/api/v1/users/1 URL to display { "id": 1, "name": "Alice", "email": " alice@example.com " } ?

+5
source share
4 answers

Here is a basic working example ...

Step 1. Create a phoenix application.

e.g. exjson for ExampleJson or whatever your other name is

 mix phoenix.new exjson --no-ecto --no-brunch --no-html 
Step 2. Configure the router

Add this area to the web / router.ex file

  scope "/api/v1", Exjson do pipe_through :api resources "/users", UserController end 
Step 3: Put data accessible somewhere in the application
 priv/data/MOCK_DATA.json 
Step 4: Configure UserController

Think of the user controller as having several actions (functions) where the conn struct is served 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: Configure UserView

You can also think of representing users as functions that will appropriately display data received from the controller. In this case, you are using json data, so phoenix has some built-in functions to help with this.

 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 
+9
source

To give you real code to get you started, this is the easiest 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 may be typos, but you get the basic idea ...

+8
source

Since you are just echoing the JSON for the endpoint /users , in this case you do not need a call to Poison.decode/1 , which does unnecessary decoding / encoding of JSON.

So, adapting Patrick's code:

 defmodule MyApp.UserController do @mock_data_string ( Application.app_dir(:my_app, "priv/mock_data/users.json") |> File.read! ) def index(conn, _params) do conn |> put_resp_content_type("application/json") |> send_resp(200, @mock_data_string) end end 

However, for the endpoint /users/1 it is better to extract the values ​​using Poison.decode/1 , as @stephen_m's answer illustrates.

+2
source

If the file is static (does not change for the progress of the service), you can read it when the application is compiled in your controller. Examine the module parameters (those that you define in your module, outside the functions). Thus, I will understand once.

If this file is dynamic, you may need to read it every time you call the API and analyze it. Not recommended, as reading a file from an IO drive will slow it down.

In any case, the result of the file processed by Map can then be transferred to the presentation and visualized, without distinction with the database.

Edit: another suggestion is to reformat your JSON (if possible) and have id as the key, and the rest of the data as the value. Thus, searching by id will be very fast, just like the index of the primary key in the database.

+1
source

Source: https://habr.com/ru/post/1241554/


All Articles