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 Array
s/Hash
es 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:
:player_move => "rock", :comp_move => "paper", :outcome => "lost" } response_hash = {
We can then convert this into a String
in JSON format with .to_json
:
response_hash.to_json
returns:
"{\"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_json
displays:
{"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
"rock", "paper", "scissors"]
moves = [
comp_move = moves.sample
if comp_move == "rock"
"tied"
outcome = elsif comp_move == "paper"
"lost"
outcome = elsif comp_move == "scissors"
"won"
outcome = end
:player_move => "rock", :comp_move => "paper", :outcome => "lost" }
response_hash = {
:plain => response_hash.to_json })
render({ end
end
Congratulations — you just built your first API endpoint! 🙌🏾