15

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
1
  • 2
    Please read "minimal reproducible example". What does companies.json contain? Have you reduced your code to the bare minimum that demonstrates the problem? Often that task will reveal the problem. Commented Oct 16, 2016 at 16:52

2 Answers 2

13

@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?

Sign up to request clarification or add additional context in comments.

Comments

12

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

2 Comments

hi @Phrogz, thank you, but I am getting the same result with your snippet. There's no company object and the array is Ruby instead json.
You can't get the same result; The way @Phrogz does it is serializing the array of hashes into JSON. Your way is creating an array of JSON serialized hashes. There's a big difference.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.