Search code examples
jsonrubyopenstruct

Ruby Parsing json array with OpenStruct


I'm trying to parse a json file with OpenStruct. Json file has an array for Skills. When I parse it I get some extra "garbage" returned. How do I get rid of it?

json

{
      "Job": "My Job 1",

      "Skills": [{ "Name": "Name 1", "ClusterName": "Cluster Name 1 Skills"},{ "Name": "Name 2", "ClusterName": "Cluster Name 2 Skills"}]
}

require 'ostruct'
require 'json'


json = File.read('1.json')
job = JSON.parse(json, object_class: OpenStruct)

puts job.Skills


#<OpenStruct Name="Name 1", ClusterName="Cluster Name 1 Skills">
#<OpenStruct Name="Name 2", ClusterName="Cluster Name 2 Skills">

Solution

  • If by garbage, you mean #<OpenStruct and ">, it is just the way Ruby represents objects when called with puts. It is useful for development and debugging, and it makes it easier to understand the difference between a String, an Array, an Hash and an OpenStruct.

    If you just want to display the name and cluster name, and nothing else :

    puts job.Job
    job.Skills.each do |skill|
      puts skill.Name
      puts skill.ClusterName
    end
    

    It returns :

    My Job 1
    Name 1
    Cluster Name 1 Skills
    Name 2
    Cluster Name 2 Skills
    

    EDIT:

    When you use job = JSON.parse(json, object_class: OpenStruct), your job variable becomes an OpenStruct Ruby object, which has been created from a json file.

    It doesn't have anything to do with json though: it is not a json object anymore, so you cannot just write it back to a .json file and expect it to have the correct syntax.

    OpenStruct doesn't seem to work well with to_json, so it might be better to remove object_class: OpenStruct, and just work with hashes and arrays.

    This code reads 1.json, convert it to a Ruby object, adds a skill, modifies the job name, writes the object to 2.json, and reads it again as JSON to check that everything worked fine.

    require 'json'
    
    json = File.read('1.json')
    job = JSON.parse(json)
    
    job["Skills"] << {"Name" => "Name 3", "ClusterName" => "Cluster Name 3 Skills"}
    job["Job"] += " (modified version)"
    
    # job[:Fa] = 'blah'
    
    File.open('2.json', 'w'){|out|
      out.puts job.to_json
    } 
    
    require 'pp'
    pp JSON.parse(File.read('2.json'))
    
    # {"Job"=>"My Job 1 (modified version)",
    # "Skills"=>
    #  [{"Name"=>"Name 1", "ClusterName"=>"Cluster Name 1 Skills"},
    #   {"Name"=>"Name 2", "ClusterName"=>"Cluster Name 2 Skills"},
    #   {"Name"=>"Name 3", "ClusterName"=>"Cluster Name 3 Skills"}]}