runski74 runski74 - 3 days ago 5
JSON Question

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">

Answer

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"}]}
Comments