Dans Rails, comment rendre JSON à l'aide d'une vue?

125

Supposons que vous soyez dans votre contrôleur d'utilisateurs et que vous souhaitiez obtenir une réponse json pour une demande d'exposition, ce serait bien si vous pouviez créer un fichier dans vos vues / utilisateurs / dir, nommé show.json et après vos utilisateurs # show l'action est terminée, il restitue le fichier.

Actuellement, vous devez faire quelque chose du genre:

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

Mais ce serait bien si vous pouviez simplement créer un fichier show.json qui sera automatiquement rendu comme suit:

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

Cela me sauverait des tonnes de chagrin et effacerait cette sensation horriblement sale que je ressens lorsque je rendrai mon json dans le contrôleur

Matthieu
la source
En regardant ce post maintenant, il semble que cela ne me sauverait pas beaucoup, mais j'ai des cas plus compliqués, croyez-moi quand je dis que cela me cause des maux de tête
Matthieu
1
Dans Rails 3, vous pouvez simplement appeler format.jsonavec un show.json.erbfichier. Voyez ma réponse.
James Lim

Réponses:

64

Vous devriez pouvoir faire quelque chose comme ça dans votre respond_tobloc:

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

qui rendra le modèle au format app/views/users/_show.json.erb.

Alex Reisner
la source
5
C'est bien, mais vous trouverez rapidement que erb est un moyen pénible de générer json. Découvrez ma réponse pour quelques alternatives.
tybro0103
1
Existe-t-il un moyen de le faire sans utiliser de partiel?
Wylliam Judd
55

Essayez d'ajouter une vue users/show.json.erbCela devrait être rendu lorsque vous faites une demande pour le format JSON, et vous obtenez l'avantage supplémentaire d'être rendu par erb aussi, donc votre fichier pourrait ressembler à ceci

{
    "first_name": "<%= @user.first_name.to_json %>",
    "last_name": "<%= @user.last_name.to_json %>"
}
erik
la source
9
Vous voudrez peut-être utiliser à la @user.first_name.to_jsonplace de escape_javascript. Il existe des différences subtiles entre ce que JS permet et ce qui est strictement JSON. (Et ces différences deviennent importantes à mesure que les navigateurs implémentent leurs propres analyseurs JSON.)
James A. Rosen
1
Vous devriez probablement changer les guillemets simples en guillemets doubles, car JSON (contrairement à JS) n'accepte que les chaînes entre guillemets.
Abe Voelker
1
C'est bien, mais vous trouverez rapidement que erb est un moyen pénible de générer json. Découvrez ma réponse pour quelques alternatives.
tybro0103
Je sais que c'est une vieille réponse, mais c'est complètement faux. to_json renverra déjà une chaîne json formatée "", donc le json résultant ne sera jamais valide avec des guillemets supplémentaires ("" valeur ""). De plus, si le prénom de l'utilisateur est nul, le json résultant aura la chaîne "null" comme valeur. <% = Utilise également l'échappement html qui modifiera les caractères html dans les données d'entrée.
d4n3
Je pense que vous devez également supprimer les guillemets, <%= xyz.to_json %>sinon vous vous retrouverez avec des guillemets supplémentaires.
akostadinov
32

Comme d'autres l'ont mentionné, vous avez besoin d'une vue users / show.json, mais il existe des options à considérer pour le langage de création de modèles ...

ERB

Fonctionne hors de la boîte. Idéal pour le HTML, mais vous trouverez rapidement que c'est affreux pour JSON.

RABL

Bonne solution. Vous devez ajouter une dépendance et apprendre son DSL.

Générateur JSON

Même accord que RABL: Bonne solution. Vous devez ajouter une dépendance et apprendre son DSL.

Rubis uni

Ruby est génial pour générer du JSON et il n'y a rien de nouveau à apprendre car vous pouvez appeler to_jsonun objet Hash ou AR. Enregistrez simplement l'extension .rb pour les modèles (dans un initialiseur):

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

Créez ensuite la vue users / show.json.rb:

@user.to_json

Pour plus d'informations sur cette approche, consultez http://railscasts.com/episodes/379-template-handlers

tybro0103
la source
7
Notez que dans les rails 4, le gestionnaire de modèles .ruby est enregistré par défaut sur github.com/rails/rails/commit/de1060f4e02925c12004f2 , vous pouvez donc ignorer l'enregistrement .rb et nommer votre fichier users / show.json.ruby.
Tim Diggins du
1
De plus, pour mettre à jour cela davantage, json_builder a été remplacé par github.com/rails/jbuilder .
Tim Diggins
27

RABL est probablement la meilleure solution à ce problème que j'ai vue si vous recherchez une alternative plus propre à la syntaxe ERb. json_builder et argonaut, qui sont d'autres solutions, semblent quelque peu obsolètes et ne fonctionneront pas avec Rails 3.1 sans quelques correctifs.

RABL est disponible via un gem ou consultez le référentiel GitHub; de bons exemples aussi

https://github.com/nesquena/rabl

zapnap
la source
21

Juste pour mettre à jour cette réponse pour le bien des autres qui se retrouvent sur cette page.

Dans Rails 3, il vous suffit de créer un fichier à views/users/show.json.erb. L' @userobjet sera disponible pour la vue (tout comme il le serait pour le HTML.) Vous n'en avez même to_jsonplus besoin .

Pour résumer, c'est juste

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

et

/* views/users/show.json.erb */
{
    "name" : "<%= @user.name %>"
}
James Lim
la source
1
J'ai répondu à cela il y a 1,5 ans. De nos jours, j'utilise simplement respond_with chaque fois que j'ai besoin de JSON, par exemple respond_with @user, only: [:name]. Reportez-vous à ce didacticiel pour plus d'informations.
James Lim
1
Juste pour ajouter à cette réponse, cela est en fait dangereux pour deux raisons: cela permet l'injection à partir des données utilisateur car il n'échappe pas aux nouvelles lignes et aux barres obliques inverses, et aussi <% = html échappe les données donc par exemple Sean O'Connor aura son nom mutilé à Sean O & apos; Connor.
d4n3 le
10

Ajoutez simplement le show.json.erbfichier avec le contenu

<%= @user.to_json %>

Parfois, cela est utile lorsque vous avez besoin de méthodes d'assistance supplémentaires qui ne sont pas disponibles dans le contrôleur, c'est-à-dire image_path(@user.avatar)ou quelque chose pour générer des propriétés supplémentaires dans JSON:

<%= @user.attributes.merge(:avatar => image_path(@user.avatar)).to_json %>
Priit
la source
8
Il faudrait <%= raw(@user.to_json) %>éviter l'échappement HTML. Ce que je fais, c'est que je compte sur to_json tant qu'il me donne ce que je veux, mais quand je veux faire autre chose, je le modélise avec ce qui est habituellement un fichier { :blah => @user.the_blah }.to_json.
clacke
0

Im nouveau à RoR c'est ce que j'ai découvert. vous pouvez directement rendre un format json

def YOUR_METHOD_HERE
  users = User.all
  render json: {allUsers: users} # ! rendering all users
END
aRtoo
la source