Ruby on Rails parse JSON file

In this post, we will see how to parse JSON files using Rails. In this process we will also understand the pros and cons of various methods used.

Table of Contents


Introduction

Before going into reading JSON using rails, let’s understand what JSON is.

What is JSON?

JSON is short for Javascript Object Notation. It is the simplest and easiest way to transfer data using the internet which makes the language extremely popular for APIs, enabling developers to work across multiple languages.

Although many 3rd party RESTful API’s deliver JSON as the response they are not exactly very readable or scalable.

For example,

Let

result = API::Domain.check('some-domain.com')


We will get the JSON response as

{




 "response": {


   "status": {    


     "code": 200,    


     "message": "OK"  


   },  


   "body": {    


     "type": "domain",    


     "name": "some-domain.com",    


     "price": "11.00",    


     "status": "Available"  


   }


 }


}


If we have to access the attributes of the response, we have to go through all the hierarchy key structure:

result = JSON.parse(result)
result['response']['body']['name'] # => 'some-domain.com' result['response']['body']['type'] # => 'domain'


Let’s suppose we want to check whether or not the domain is available(domain is available only if its status is ‘Available’ and price is less than 20)

The code will look like this:

result['response']['body']['status'] == 'Available' &&
result['response']['body']['price'].to_f < 20


As you can see, the code above is not really efficient at all, in terms of readability and scalability as you have to go through all the hierarchy in the structure to set the value etc.

Additionally, what would happen when some fields in the hierarchy structure are updated? Let’s say the field result ['response']['body'] is changed to result ['response']['data'].

As a result, the codes have to be updated to:

result['response']['body'] => result['response']['data']


Imagine if the logic is being called in multiple places, it will require multiple changes, plus the failing specs as well.

We will now look at different methods on how you can use rails to parse JSON in a scalable and efficient manner.

Creating own classes to parse JSON

One way to use rails to parse json in a scalable and effective manner is to create a class that parses the JSON response and manages the data from the json fields using the object. The problem with this approach is we need to maintain the class and have to be clear on which fields are included in the JSON.

Using JSON.parse and OpenStruct to parse JSON in rails

If you are looking for a much easier approach than creating a class in rails to parse JSON, you can use the JSON.parse and OpenStruct class.

Here is an example demonstrating using JSON. parse and openstruct in rails to parse JSON below:

 
 
{
 
 
 "response": {
 
   "status": {    
 
     "code": 200,    
 
     "message": "OK"  
 
   },  
 
   "body": {    
 
     "type": "domain",    
 
     "name": "some-domain.com",    
 
     "price": "11.00",    
 
     "status": "Available"  
 
   }
 
 }
 
}


Step1: To use rails to parse JSON, convert the json to be an object:

require 'json'
object = JSON.parse(json, object_class: OpenStruct)


Now we got the object variable which is an instance of OpenStruct and responses to method names as keys of the JSON.

object.respond_to?(:response) => true


If there are more subsequence keys after the response , the object.response will return another instance of the OpenStruct class holding the subsequence methods as those subsequence keys.

object.response.status.code => 200
object.response.body.type => domain
object.response.body.price => 11.00
 


Here is a complete example demonstrating the use of openstruct and json parse in rails to parse JSON.

{
  "firstname": "jeff",
  "lastname": "durand",
  "address": {
    "street": "22 charlotte rd",
    "zipcode": "01013"
    "residents": 1
  }
}


To use rails openstruct class to parse json, we need to require the ostruct library which contains the OpenStruct class definition as it is not part of the Ruby Core.

require 'json'

# OpenStruct is not included by default so you have to add it.

require 'ostruct'

json_string = '{"firstname":"jeff",

"lastname":"durand",
"address": { "street":"22 charlotte rd", 
"zipcode":"01013", "residents": 3 }}'

json_object = JSON.parse(json_string, object_class: OpenStruct)

puts json_object.address.street

# result: 22 charlotte rd


One key point to note is that the object_class can be any class, so it’s completely possible to create your own class as mentioned above that inherits from OpenStruct but has better methods for object serialization or access.