In Rails, come si esegue il rendering di JSON usando una vista?


125

Supponiamo che tu sia nel controller degli utenti e desideri ottenere una risposta json per una richiesta di spettacolo, sarebbe bello poter creare un file nelle tue viste / utenti / dir, chiamato show.json e dopo i tuoi utenti # show l'azione è completata, esegue il rendering del file.

Attualmente devi fare qualcosa del tipo:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json{
      render :json => @user.to_json
    }
  end
end

Ma sarebbe bello se potessi semplicemente creare un file show.json che viene automaticamente reso in questo modo:

def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

Questo mi risparmierebbe un sacco di dolore, e toglierebbe quella sensazione terribilmente sporca che provo quando rendo il mio json nel controller


Guardando questo post ora, sembra che questo non mi risparmierebbe molto, ma ho casi più complicati, fidati di me quando dico che questo mi sta causando mal di testa
Matthew

1
In Rails 3, puoi semplicemente chiamare format.jsoncon un show.json.erbfile. Vedi la mia risposta
James Lim,

Risposte:


64

Dovresti essere in grado di fare qualcosa del genere nel tuo respond_toblocco:

respond_to do |format|
    format.json 
    render :partial => "users/show.json"
end

che renderà il modello in app/views/users/_show.json.erb.


5
Questo è buono, ma scoprirai rapidamente che l'ERB è un modo doloroso per generare json. Controlla la mia risposta per alcune alternative.
tybro0103,

1
C'è un modo per farlo senza usare un parziale?
Wylliam Judd,

55

Prova ad aggiungere una vista users/show.json.erbQuesto dovrebbe essere reso quando fai una richiesta per il formato JSON e ottieni l'ulteriore vantaggio di essere reso anche da ERB, quindi il tuo file potrebbe assomigliare a questo

{
    "first_name": "<%= @user.first_name.to_json %>",
    "last_name": "<%= @user.last_name.to_json %>"
}

9
Potresti voler usare @user.first_name.to_jsoninvece di escape_javascript. Ci sono alcune sottili differenze tra ciò che JS consente e ciò che è strettamente JSON. (E queste differenze stanno diventando importanti quando i browser implementano i propri parser JSON.)
James A. Rosen,

1
Probabilmente dovresti cambiare le virgolette singole in virgolette doppie, poiché JSON (a differenza di JS) accetta solo stringhe tra virgolette doppie.
Abe Voelker,

1
Questo è buono, ma scoprirai rapidamente che l'ERB è un modo doloroso per generare json. Controlla la mia risposta per alcune alternative.
tybro0103,

So che questa è una vecchia risposta, ma è completamente sbagliata. to_json restituirà una stringa json formattata "" già, quindi il json risultante non sarà mai valido con virgolette aggiuntive ("" valore ""). Inoltre, se il nome utente è zero, il json risultante avrà la stringa "null" come valore. Anche <% = usa l'escape HTML che manipolerà i caratteri HTML nei dati di input.
d4n3,

Penso che anche tu debba rimuovere le virgolette, <%= xyz.to_json %>altrimenti ti rimarrebbero citazioni extra.
Akostadinov,

32

Come altri hanno già detto, hai bisogno di una vista utenti / show.json, ma ci sono opzioni da considerare per il linguaggio dei modelli ...

ERB

Funziona fuori dalla scatola. Ottimo per HTML, ma scoprirai rapidamente che è terribile per JSON.

Rabl

Buona soluzione Devi aggiungere una dipendenza e imparare il suo DSL.

JSON Builder

Stesso affare di RABL: buona soluzione. Devi aggiungere una dipendenza e imparare il suo DSL.

Rubino semplice

Ruby è fantastico nel generare JSON e non c'è nulla di nuovo da imparare come puoi chiamare to_jsonun Hash o un oggetto AR. Basta registrare l'estensione .rb per i modelli (in un inizializzatore):

ActionView::Template.register_template_handler(:rb, :source.to_proc)

Quindi creare la vista utenti / show.json.rb:

@user.to_json

Per ulteriori informazioni su questo approccio, consultare http://railscasts.com/episodes/379-template-handlers


7
Si noti che nelle rotaie 4, il gestore di modelli .ruby è registrato per impostazione predefinita github.com/rails/rails/commit/de1060f4e02925c12004f2 in modo da poter saltare la registrazione di .rb e denominare gli utenti del file / show.json.ruby.
Tim Diggins,

1
Inoltre, per aggiornarlo ulteriormente, json_builder è stato sostituito da github.com/rails/jbuilder .
Tim Diggins,

27

RABL è probabilmente la soluzione più bella a ciò che ho visto se stai cercando un'alternativa più pulita alla sintassi ERb. json_builder e argonaut, che sono altre soluzioni, sembrano entrambi piuttosto obsoleti e non funzioneranno con Rails 3.1 senza alcune patch.

RABL è disponibile tramite gemma o controlla il repository GitHub; buoni esempi anche

https://github.com/nesquena/rabl


21

Solo per aggiornare questa risposta per il bene degli altri che finiscono in questa pagina.

In Rails 3, devi solo creare un file su views/users/show.json.erb. L' @useroggetto sarà disponibile per la vista (proprio come sarebbe per HTML). Non è nemmeno necessarioto_json più .

Per riassumere, è solo

# users contoller
def show
  @user = User.find( params[:id] )
  respond_to do |format|
    format.html
    format.json
  end
end

e

/* views/users/show.json.erb */
{
    "name" : "<%= @user.name %>"
}

1
Ho risposto 1,5 anni fa. Al giorno d'oggi uso solo respond_with ogni volta che ho bisogno di JSON ad es respond_with @user, only: [:name]. Fare riferimento a questo tutorial per ulteriori informazioni.
James Lim,

1
Solo per aggiungere a questa risposta, questo è in realtà pericoloso per due motivi: consente l'iniezione dai dati dell'utente perché non sfugge a nuove righe e barre rovesciate, e anche <% = html sfugge ai dati, ad esempio Sean O'Connor avrà il suo nome ridotto a Sean O & apos Connor.
d4n3,

10

Basta aggiungere il show.json.erbfile con il contenuto

<%= @user.to_json %>

A volte è utile quando sono necessari alcuni metodi di supporto extra che non sono disponibili nel controller, ovvero image_path(@user.avatar)qualcosa per generare proprietà aggiuntive in JSON:

<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>

8
Dovrebbe essere <%= raw(@user.to_json) %>per evitare la fuga dell'HTML. Quello che faccio è che mi affido a to_json fintanto che mi dà quello che voglio, ma quando voglio fare qualcos'altro lo modello con ciò che di solito è un { :blah => @user.the_blah }.to_json.
clacke


0

Sono nuovo di RoR questo è quello che ho scoperto. puoi eseguire il rendering diretto di un formato json

def YOUR_METHOD_HERE
  users = User.all
  render json: {allUsers: users} # ! rendering all users
END
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.