2.17 Addendum: Rendering JSON
Imagine that we wanted to build a native iPhone app that asked our server for some information; in this simple example, for a random computer move and an outcome, but in the real-world things like the local weather given a latitude and a longitude.
Rather than rendering a pre-defined message in plain text, it’s usually more helpful to the iPhone developer to render the data in JSON format, so that they can parse it, easily fetch whichever values they need, and assemble their own interface.
Here is some JSON that would be convenient for an external application to parse:
{ "player_move":"rock", "comp_move":"paper", "outcome":"lost" }Notice that JSON uses strings as keys — this is because JavaScript doesn’t have the equivalent of Ruby’s Symbol class. Also, there are no hash rockets; JSON just uses colons to separate keys and values.
Fortunately, just as it was easy for us to convert a String containing JSON into Ruby Arrays/Hashes using the JSON.parse method, it is also easy for us to go in the other direction: both Array and Hash have methods called .to_json. Let’s create a Ruby Hash that resembles the JSON above:
response_hash = { :player_move => "rock", :comp_move => "paper", :outcome => "lost" }We can then convert this into a String in JSON format with .to_json:
response_hash.to_jsonreturns:
"{\"player_move\":\"rock\",\"comp_move\":\"paper\",\"outcome\":\"lost\"}"The \" represents double-quotes; we need the backslash, known as an “escape”, because we’re already within a double-quoted string and don’t want to terminate it. You can puts the string to see it formatted:
puts response_hash.to_jsondisplays:
{"player_move":"rock","comp_move":"paper","outcome":"lost"}
Great! That means we can update our action if we want to send back JSON instead:
class ApplicationController < ActionController::Base
def play_rock
moves = ["rock", "paper", "scissors"]
comp_move = moves.sample
if comp_move == "rock"
outcome = "tied"
elsif comp_move == "paper"
outcome = "lost"
elsif comp_move == "scissors"
outcome = "won"
end
response_hash = { :player_move => "rock", :comp_move => "paper", :outcome => "lost" }
render({ :plain => response_hash.to_json })
end
endCongratulations — you just built your first API endpoint! 🙌🏾