[英]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. 我想将数据用作手动编写的JSON文件,而不是从数据库中获取数据。 Suppose my data is this:
假设我的数据是这样的:
[
{ "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's written in a file called MOCK_DATA.json
. 它写在一个名为
MOCK_DATA.json
的文件中。 What should I do to render this file when I access the localhost:port/api/v1/users
url? 当我访问
localhost:port/api/v1/users
时,我该怎么做才能呈现这个文件localhost:port/api/v1/users
url? How about the localhost:port/api/v1/users/1
url to show { "id": 1, "name": "Alice", "email": "alice@example.com" }
? localhost:port/api/v1/users/1
url如何显示{ "id": 1, "name": "Alice", "email": "alice@example.com" }
?
Here is a basic working example... 这是一个基本的工作示例......
eg, exjson for ExampleJson or whatever name your like 例如,exjson用于ExampleJson或任何你喜欢的名字
scope "/api/v1", Exjson do
pipe_through :api
resources "/users", UserController
end
Step 2: Set up the router
Add this scope to the web/router.ex file 将此范围添加到web / router.ex文件中
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 可以将用户控制器视为具有许多动作(函数),其中conn struct从您的phoenix端点以及任何参数输入
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. 您还可以将“用户视图”视为具有以适当方式呈现从Controller接收的数据的功能。 In this case, you are using json data so phoenix has some built in functions to help with that.
在这种情况下,您正在使用json数据,因此phoenix具有一些内置函数来帮助实现这一点。
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
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. 然后将您的假数据保存在项目内的
priv/mock_data/users.json
。 There might be typos in there, but you get the basic idea... 那里可能有拼写错误,但你得到的基本想法......
Since you're just echoing the JSON back for the /users
endpoint, in that case you don't need the Poison.decode/1
call which does unnecessary decoding/encoding of the JSON. 由于您只是为
/users
端点回显JSON,在这种情况下,您不需要Poison.decode/1
调用,它会对JSON进行不必要的解码/编码。
So, adapting Patrick's code: 所以,调整Patrick的代码:
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 /users/1
endpoint, it is best to extract values by using Poison.decode/1
, as @stephen_m's answer illustrates. 但是,对于
/users/1
端点,最好使用Poison.decode/1
提取值,如@ stephen_m的答案所示。
If the file is static (does not change for the course of the service running) then you can read it when the app compiles in your controller. 如果文件是静态的(在服务运行过程中没有改变),那么当应用程序在您的控制器中编译时,您可以读取它。 Look into module parameters (the ones you define in your module, outside of functions).
查看模块参数(您在模块中定义的参数,在函数之外)。 This way i'll be parsed once.
这样我将被解析一次。
If this file is dynamic then you may need to read it every time the API is called and parse it. 如果此文件是动态的,那么您可能需要在每次调用API时读取它并对其进行解析。 Not really advised since reading a file from disk IO will slow it down.
没有真正建议,因为从磁盘IO读取文件会降低速度。
In any case the result of the file, parsed to a Map can then be passed in into the view and rendered, no difference from the database. 在任何情况下,解析到Map的文件结果都可以传入视图并呈现,与数据库没有区别。
Edit: another suggestion is to reformat your JSON (if possible) and have id
as a key and the rest of the data as a value. 编辑:另一个建议是重新格式化您的JSON(如果可能)并将
id
作为键,其余数据作为值。 This way lookups by id
will be very fast, just like a primary key index in the database. 这样,
id
查找速度非常快,就像数据库中的主键索引一样。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.