Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create a JSON object in Ruby

Tags:

json

parsing

ruby

I am creating a JSON file with Ruby. I need to create the object "companies" within the JSON file.

Expected result:

{"companies":[
    {\"label\":\"Wayfair \",\"values\":[54]},
    {\"label\":\"Move24 \",\"values\":[29]},
    {\"label\":\"Auto1 \",\"values\":[23]},
...
]}

What I am getting:

[  
   "{\"label\":\"Wayfair \",\"values\":[54,54]}",
   "{\"label\":\"Move24 \",\"values\":[29,29]}",
   "{\"label\":\"GetYourGuide \",\"values\":[28,28]}",
   "{\"label\":\"Auto1.com \",\"values\":[20,20]}", ...
]

My code:

data_hash = data_hash.map {|k,v| {label: k, values: v}}

companies_json = []

data_hash.each do |hash|
  companies_json << hash.to_json
end

File.open('companies.json', 'w') do |f|
  f << companies_json
end
like image 815
catch22 Avatar asked Oct 16 '16 16:10

catch22


People also ask

What is JSON in Ruby?

JavaScript Object Notation (JSON)¶ ↑ JSON is a lightweight data-interchange format. A JSON value is one of the following: Double-quoted text: "foo" . Number: 1 , 1.0 , 2.0e2 .


2 Answers

The core of your problem is that you are creating an array of JSON strings, instead of an array and then making that JSON. Instead of:

companies_json = []

data_hash.each do |hash|
  companies_json << hash.to_json
end

do:

companies = []

data_hash.each do |hash|
  companies << hash
end

companies_json = companies.to_json
like image 122
Phrogz Avatar answered Oct 17 '22 09:10

Phrogz


@Phrogz has the correct answer. This is to provide a bit more explanation of what's happening:

require 'json'

foo = {'a' => 1}
foo.to_json # => "{\"a\":1}"

That's what a JSON serialized hash looks like. It's a string containing escaped quotes wrapping the key, with : delimiting the key and value pair. JSON is always an array, "[...]", or a hash, "{...}", and in either case it's a String. That's just what serializing does and how JSON works.

[foo.to_json] # => ["{\"a\":1}"]
[foo.to_json].class # => Array

That's an array containing a JSON serialized hash, which is what you're doing. You can tell it's not serialized correctly because it's an Array, not a String. The surrounding [...] are outside the quotes whereas in JSON they're inside the quotes:

[].to_json # => "[]"
{}.to_json # => "{}"

Moving on...

[foo].to_json # => "[{\"a\":1}]"
[foo].to_json.class # => String

That's a serialized array of hashes. In this case it's a single hash, but it's sufficient for this example. It's a String after serializing, which you can tell because the array [...] is inside the surrounding quotes.


If you really want to understand this stuff I highly recommend reading both the JSON home page, along with Ruby's JSON, YAML and Psych documentation. JSON is nearly a subset of YAML, so knowing YAML and how Psych implements it is really helpful as you move into working with JSON, YAML and the internet.

"Fer instance":

json_hash = '{"a":1}'
yaml_hash = "---\na: 1"

require 'yaml'
YAML.load(json_hash) # => {"a"=>1}
YAML.load(yaml_hash) # => {"a"=>1}

Psych.load(json_hash) # => {"a"=>1}
Psych.load(yaml_hash) # => {"a"=>1}

require 'json'
JSON[json_hash] # => {"a"=>1}
JSON[yaml_hash] # => JSON::ParserError: 743: unexpected token at '---\na: 1'

Kinda blows your mind doesn't it?

like image 40
the Tin Man Avatar answered Oct 17 '22 11:10

the Tin Man