2016-01-26 11 views
5

Invece di recuperare i dati da un database, voglio utilizzare come dati un file JSON scritto manualmente. Supponiamo che i miei dati è questo:Come eseguire il rendering di un file JSON con il framework Phoenix?

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

ed è scritto in un file chiamato MOCK_DATA.json. Cosa devo fare per eseguire il rendering di questo file quando accedo all'URL localhost:port/api/v1/users? Che ne dici dell'URL localhost:port/api/v1/users/1 per mostrare { "id": 1, "name": "Alice", "email": "[email protected]" }?

+1

Quindi, vuoi solo prendere in giro la risposta per iniziare rapidamente e sostituirla con un'implementazione "reale" in seguito? Questo non deve essere pronto per la produzione, immagino? –

+0

@PatrickOscity si, esattamente. –

risposta

9

Ecco un esempio di lavoro di base ...

Passaggio 1: Creare l'applicazione Phoenix

ad esempio, exjson per ExampleJson o qualsiasi altro nome vostro simile

mix phoenix.new exjson --no-ecto --no-brunch --no-html 
Fase 2: impostare il router

Aggiungere questo ambito al web/file di router.ex

scope "/api/v1", Exjson do 
    pipe_through :api 
    resources "/users", UserController 
    end 
Fase 3: Mettere i dati finti qualche ac cessibili al app
priv/data/MOCK_DATA.json 
Fase 4: Impostare l'UsersController

Pensate Controller utenti ad avere una serie di azioni (funzioni) dove il conn struct viene immessa dal punto finale Phoenix insieme a tutti parametri

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 
Fase 5: Configurare l'UsersView

Si può anche pensare degli utenti Vedi come con funzioni che renderanno i dati ricevuti dal controller in modo appropriato. In questo caso, stai utilizzando i dati JSON così phoenix ha alcune funzioni incorporate per aiutarti.

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 
+0

Se invii json nella tua api, allora termini di rendering dei dati sul browser, spesso oggigiorno, gli sviluppatori utilizzano le cosiddette framework "Single Page Apps" per creare l'interfaccia utente (componente browser). Ad esempio [Aurelia] (http://aurelia.io/), [Angular2] (https://angular.io/) ma che è solo per citarne alcuni, ce ne sono molti .... –

+0

Qual è il ': parametro code.priv_dir (: exjson) 'nella funzione' Path.join'? Ho cercato il codice sorgente della fenice ma la mia ricerca è risultata vuota. –

+1

È una funzione da una [biblioteca di erlang] (http://erlang.org/doc/man/code.html#priv_dir-1) .. ottiene solo la cartella privata. I file in questa cartella sono disponibili per l'applicazione. –

1

Se il file è statico (non cambia durante l'esecuzione del servizio), è possibile leggerlo quando l'app viene compilata nel controller. Guarda i parametri del modulo (quelli che definisci nel tuo modulo, al di fuori delle funzioni). In questo modo sarò analizzato una volta.

Se questo file è dinamico, potrebbe essere necessario leggerlo ogni volta che viene chiamata l'API e analizzarlo. Non proprio consigliato dal momento che la lettura di un file dal disco IO lo rallenterà.

In ogni caso il risultato del file, analizzato su una mappa può essere passato nella visualizzazione e reso, nessuna differenza dal database.

Modifica: un altro suggerimento è di riformattare il JSON (se possibile) e avere id come chiave e il resto dei dati come valore. In questo modo le ricerche di id saranno molto veloci, proprio come un indice di chiave primaria nel database.

+0

Sono un principiante, sia a Phoenix che in Elisir, quindi non ho capito la tua risposta. Potresti darmi qualche esempio di codice? Inoltre, grazie per i tuoi suggerimenti sulle prestazioni, ma a questo punto non so nemmeno come rendere i dati sul browser, quindi apprezzerei le istruzioni specifiche su quell'area. –

8

Per darvi un codice vero e proprio per iniziare, questa è la cosa più semplice che posso pensare:

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 

Poi basta salvare i dati falsi nel priv/mock_data/users.json all'interno del vostro progetto. Potrebbero esserci errori di battitura, ma hai un'idea di base ...

2

Dato che si sta solo riecheggiando il JSON per l'endpoint /users, in tal caso non è necessaria la chiamata Poison.decode/1 che esegue la decodifica/codifica non necessaria del JSON.

Quindi, adattando il codice di 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 

Tuttavia, per il /users/1 endpoint, è meglio estrarre i valori utilizzando Poison.decode/1, come @ di stephen_m risposta illustra.

+0

Che bello! Ho solo bisogno di qualcosa di simile (basta inoltrare i dati JSON da un altro server tramite Phoenix). Lo proverò! – fenton

Problemi correlati