[ruby-on-rails] How do I parse JSON with Ruby on Rails?

I'm looking for a simple way to parse JSON, extract a value and write it into a database in Rails.

Specifically what I'm looking for, is a way to extract shortUrl from the JSON returned from the bit.ly API:

{
  "errorCode": 0,
  "errorMessage": "",
  "results":
  {
    "http://www.foo.com":
    {
       "hash": "e5TEd",
       "shortKeywordUrl": "",
       "shortUrl": "http://bit.ly/1a0p8G",
       "userHash": "1a0p8G"
    }
  },
  "statusCode": "OK"
}

And then take that shortUrl and write it into an ActiveRecord object associated with the long URL.

This is one of those things that I can think through entirely in concept and when I sit down to execute I realize I've got a lot to learn.

This question is related to ruby-on-rails ruby json

The answer is


The Oj gem (https://github.com/ohler55/oj) should work. It's simple and fast.

http://www.ohler.com/oj/#Simple_JSON_Writing_and_Parsing_Example

require 'oj'

h = { 'one' => 1, 'array' => [ true, false ] }
json = Oj.dump(h)

# json =
# {
#   "one":1,
#   "array":[
#     true,
#     false
#   ]
# }

h2 = Oj.load(json)
puts "Same? #{h == h2}"
# true

The Oj gem won't work for JRuby. For JRuby this (https://github.com/ralfstx/minimal-json) or this (https://github.com/clojure/data.json) may be good options.


RUBY is case sensitive.

require 'json' # json must be lower case

JSON.parse(<json object>)  

for example

JSON.parse(response.body) # JSON must be all upper-case

This answer is quite old. pguardiario's got it.

One site to check out is JSON implementation for Ruby. This site offers a gem you can install for a much faster C extension variant.

With the benchmarks given their documentation page they claim that it is 21.500x faster than ActiveSupport::JSON.decode

The code would be the same as Milan Novota's answer with this gem, but the parsing would just be:

parsed_json = JSON(your_json_string)

These answers are a bit dated. Therefore I give you:

hash = JSON.parse string

Rails should automagically load the json module for you, so you don't need to add require 'json'.


Parsing JSON in Rails is quite straightforward:

parsed_json = ActiveSupport::JSON.decode(your_json_string)

Let's suppose, the object you want to associate the shortUrl with is a Site object, which has two attributes - short_url and long_url. Than, to get the shortUrl and associate it with the appropriate Site object, you can do something like:

parsed_json["results"].each do |longUrl, convertedUrl|
  site = Site.find_by_long_url(longUrl)
  site.short_url = convertedUrl["shortUrl"]
  site.save
end

This can be done as below, just need to use JSON.parse, then you can traverse through it normally with indices.

#ideally not really needed, but in case if JSON.parse is not identifiable in your module  
require 'json'

#Assuming data from bitly api is stored in json_data here

json_data = '{
  "errorCode": 0,
  "errorMessage": "",
  "results":
  {
    "http://www.foo.com":
    {
       "hash": "e5TEd",
       "shortKeywordUrl": "",
       "shortUrl": "http://whateverurl",
       "userHash": "1a0p8G"
    }
  },
  "statusCode": "OK"
}'

final_data = JSON.parse(json_data)
puts final_data["results"]["http://www.foo.com"]["shortUrl"]

require 'json'

hash = JSON.parse string

work with the hash and do what you want to do.


require 'json'
out=JSON.parse(input)

This will return a Hash


You can try something like this:

def details_to_json
{
  :id                    => self.id, 
  :credit_period_type    => self.credit_period_type,
  :credit_payment_period => self.credit_payment_period,

 }.to_json
end

Ruby's bundled JSON is capable of exhibiting a bit of magic on its own.

If you have a string containing JSON serialized data that you want to parse:

JSON[string_to_parse]

JSON will look at the parameter, see it's a String and try decoding it.

Similarly, if you have a hash or array you want serialized, use:

JSON[array_of_values]

Or:

JSON[hash_of_values]

And JSON will serialize it. You can also use the to_json method if you want to avoid the visual similarity of the [] method.

Here are some examples:

hash_of_values = {'foo' => 1, 'bar' => 2}
array_of_values = [hash_of_values]

JSON[hash_of_values] 
# => "{\"foo\":1,\"bar\":2}"

JSON[array_of_values] 
# => "[{\"foo\":1,\"bar\":2}]"

string_to_parse = array_of_values.to_json
JSON[string_to_parse]
# => [{"foo"=>1, "bar"=>2}]

If you root around in JSON you might notice it's a subset of YAML, and, actually the YAML parser is what's handling JSON. You can do this too:

require 'yaml'

YAML.load(string_to_parse)
# => [{"foo"=>1, "bar"=>2}]

If your app is parsing both YAML and JSON, you can let YAML handle both flavors of serialized data.


Here's what I would do:

json = "{\"errorCode\":0,\"errorMessage\":\"\",\"results\":{\"http://www.foo.com\":{\"hash\":\"e5TEd\",\"shortKeywordUrl\":\"\",\"shortUrl\":\"http://b.i.t.ly/1a0p8G\",\"userHash\":\"1a0p8G\"}},\"statusCode\":\"OK\"}"

hash = JSON.parse(json)
results = hash[:results]

If you know the source url then you can use:

source_url = "http://www.foo.com".to_sym

results.fetch(source_url)[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

If you don't know the key for the source url you can do the following:

results.fetch(results.keys[0])[:shortUrl]
=> "http://b.i.t.ly/1a0p8G"

If you're not wanting to lookup keys using symbols, you can convert the keys in the hash to strings:

results = json[:results].stringify_keys

results.fetch(results.keys[0])["shortUrl"]
=> "http://b.i.t.ly/1a0p8G"

If you're concerned the JSON structure might change you could build a simple JSON Schema and validate the JSON before attempting to access keys. This would provide a guard.

NOTE: Had to mangle the bit.ly url because of posting rules.


Here is an update for 2013.

Ruby

Ruby 1.9 has a default JSON gem with C extensions. You can use it with

require 'json'
JSON.parse ''{ "x": "y" }'
# => {"x"=>"y"}

The parse! variant can be used for safe sources. There are also other gems, which may be faster than the default implementation. Please refer to multi_json for the list.

Rails

Modern versions of Rails use multi_json, a gem that automatically uses the fastest JSON gem available. Thus, the recommended way is to use

object = ActiveSupport::JSON.decode json_string

Please refer to ActiveSupport::JSON for more information. In particular, the important line in the method source is

data = MultiJson.load(json, options)

Then in your Gemfile, include the gems you want to use. For example,

group :production do
  gem 'oj'
end

Examples related to ruby-on-rails

Embed ruby within URL : Middleman Blog Titlecase all entries into a form_for text field Where do I put a single filter that filters methods in two controllers in Rails Empty brackets '[]' appearing when using .where How to integrate Dart into a Rails app Rails 2.3.4 Persisting Model on Validation Failure How to fix "Your Ruby version is 2.3.0, but your Gemfile specified 2.2.5" while server starting Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432? Rails: Can't verify CSRF token authenticity when making a POST request Uncaught ReferenceError: React is not defined

Examples related to ruby

Uninitialized Constant MessagesController Embed ruby within URL : Middleman Blog Titlecase all entries into a form_for text field Ruby - ignore "exit" in code Empty brackets '[]' appearing when using .where find_spec_for_exe': can't find gem bundler (>= 0.a) (Gem::GemNotFoundException) How to update Ruby Version 2.0.0 to the latest version in Mac OSX Yosemite? How to fix "Your Ruby version is 2.3.0, but your Gemfile specified 2.2.5" while server starting Is the server running on host "localhost" (::1) and accepting TCP/IP connections on port 5432? How to update Ruby with Homebrew?

Examples related to json

Use NSInteger as array index Uncaught SyntaxError: Unexpected end of JSON input at JSON.parse (<anonymous>) HTTP POST with Json on Body - Flutter/Dart Importing json file in TypeScript json.decoder.JSONDecodeError: Extra data: line 2 column 1 (char 190) Angular 5 Service to read local .json file How to import JSON File into a TypeScript file? Use Async/Await with Axios in React.js Uncaught SyntaxError: Unexpected token u in JSON at position 0 how to remove json object key and value.?