Output JSON array without the class name in every array element - ruby-on-rails

The default way to output JSON in rails is some thing like:
Code:
render :json => friends.to_json(:only => [:username, :avatar_file_name, :id ])
Output
{"friends" :
[{"user":
{"avatar_file_name": "image1.jpg", "username": "user1", "id": 1}},
{"user":
{"avatar_file_name": "image2.jpg", "username": "user2", "id": 2}},
{"user":
{"avatar_file_name": "image3.jpg", "username": "user3", "id": 3}}
]}
But i want something like:
{"friends" :
{"user": [
{"avatar_file_name": "image1.jpg", "username": "user1", "id": 1},
{"avatar_file_name": "image2.jpg", "username": "user2", "id": 2},
{"avatar_file_name": "image3.jpg", "username": "user3", "id": 3}
]}
}
The class is specified by the array name.
Last.fm also uses this syntax see Last.fm 'API-user.getfriends'

The solution to this problem is commenting the line
ActiveRecord::Base.include_root_in_json = true
in initializers/new_rails_defaults.rb
Or setting ActiveRecord::Base.include_root_in_json to false.

You can use javascript to reformat it:
var json =
{
"friends" :
{ "user": [] }
}
var i = 0;
for ( x in friends )
{
json.friends.user[i].avatar_file_name = x.user.avatar_file_name; // add more fields.
i++;
}
Something among those lines.

JSON is normally used to represent objects in a text format.
So if you like the secon output you must change your objects.
The first output says:
there is a friends object which is a array of user, each user has some properties among which you chose to expose username, avatar_file_name, id
The second output says:
there is a friends object which contains a user object which is an array of unnamed objects, each unnamed objects has some properties...
This second output is not writable in JSON syntax.
It might be:
{"friends" :
{"user": [
["avatar_file_name", "username", "id"],
["image1.jpg", "user1", 1],
["image2.jpg", "user2", 2],
["image3.jpg", "user3", 3]
]}
}
This says:
there is a friends object which contains a user object which is an array of array (a table with field names on first row) ...

Related

Get some data from a table in my database - Ruby on rails

I have an association of my model Banner with Images, I need to bring all the images but only the field file, in file I have a hash in which I just want to get the url
I have this code:
Banner.find_by(event_id: #event.id).to_json(:include => [{:images => {:only => [:file]}}])
but this gets me this:
{
"id": 2,
"created_at": "2019-04-24T14:59:08.000-05:00",
"updated_at": "2019-04-24T14:59:08.000-05:00",
"event_id": 3,
"name": "ccccccccccccccccccccccssssss",
"images": [
{
"file": {
"url": "/uploads/image/file/300aecf6-b3c7-4b15-94a1-45c530efc4c4.png"
}
}
]
}
I want something like this:
{
"id": 2,
"created_at": "2019-04-24T14:59:08.000-05:00",
"updated_at": "2019-04-24T14:59:08.000-05:00",
"event_id": 3,
"name": "ccccccccccccccccccccccssssss",
"images": [
"/uploads/image/file/300aecf6-b3c7-4b15-94a1-45c530efc4c4.png"
]
}
How could I do this? Any suggestions?
Sometimes it's best to break things up into smaller pieces...
# create the query to get all the objects to prevent n+1 queries
banners = Banner.includes(images: :file)
# get the banner you want to serialize
banner = banners.find_by(event_id: #event.id)
# get all the urls for the images as an array
image_urls = banner.images.collect {|i| i.file.url }
# create the json object
json = banner.to_json.merge(images: image_urls)

Filter through nested JSON object and obtain JSON with specific keys, using Ruby

I currently have a nested JSON object which resembles
{
"People": [
{
"Name": "James",
"Age": "18",
"Gender": "Male",
"Sports": []
},
{
"Name": "Sarah",
"Age": "19",
"Gender": "Female",
"Sports": [
"Soccer",
"Basketball",
"Football"
]
}
]
}
Being new to Ruby, I aim to filter throught the entire json and return only the json object/objects in which the "Sports" array has content. So in the above scenario I expect to obtain the object below as a final outcome:
{
"Name": "Sarah",
"Age": "19",
"Gender": "Female",
"Sports": [
"Soccer",
"Basketball",
"Football"
]
}
Will I have to initiate a new method to perform such an act? Or would using regular ruby calls work in this case?
Although #philipyoo answer is right, it miss an explanation on how to "filter" the parsed JSON. If you are new to ruby, take a look at Array#keep_if : http://ruby-doc.org/core-2.2.0/Array.html#method-i-keep_if
require 'json'
people = JSON.parse("{long JSON data ... }")
people_with_sports = people.fetch('People', []).keep_if do |person|
!person.fetch('Sports', []).empty?
end
If you're getting a JSON object from a request, you want to parse it and then you can traverse the hash and arrays to find the information you need. See http://ruby-doc.org/stdlib-2.0.0/libdoc/json/rdoc/JSON.html
In your case, something like this:
require 'json'
parsed_json = JSON.parse('{"People": [ ... ]}')
parsed_json["People"].each do |person|
puts person if person["name"] == "Sarah"
end

Compare JSON structure in ruby

I have two json objects as below:
obj1= [ { "id": 4, "userId": "abc", "firstName": "abc", "lastName": "abc", "email": "abc#abc.it", "prefers" : [{"breakfast" : "bread" , "lunch" : "non-veg"}] } ]
obj2= [ { "id": 5, "userId": "def", "firstName": "def", "lastName": "def", "email": "def#def.it", "prefers" : [{"breakfast" : "egg" , "lunch" : "veg"}] } ]
Given these to objects i have to validate object2 has the same keys as in object1
diff(obj1,obj2) should give me missing keys
use keys to return an array of keys of the hash and then subtract them
obj1[0].keys - obj2[0].keys
# => array of missing keys
This Ruby JSON comparator will show you how to do it. It is designed to compare the two objects and return true if they're same, but from that you can devise a more complicated return value based on your needs.
If you only want true/false validation that the keys of both objects match, you can do:
object1.keys && object2.keys == object1.keys
That will give you a validation of matching or not.

Parse JSON with an array in Rails

I have the following JSON string returned by a remote server:
{
"users": [
{
"user_id": 1,
"name": "Chris Rivers",
},
{
"user_id": 3,
"name": "Peter Curley",
}
]
}
I'd like to iterate the users.
ActiveSupport::JSON.decode(response.body)["users"].each do |user|
puts user["name"]
end
As far as I understand, the problem is: ruby doesn't recognize ActiveSupport::JSON.decode(response.body)["users"] as an array, and thus puts returns me only the first user.
How do I solve that problem?
What you have pasted is not valid JSON. The trailing comma after on each "name" is a problem
"name": "Chris Rivers",
You'll get a LoadError trying to decode this with ActiveSupport::JSON.decode
MultiJson::LoadError: 399: unexpected token at '{"user_id": 1,"name": "Chris Rivers",},{"user_id": 3,"name": "Peter Curley",}]}'
If we clean up the JSON, turning it into something ActiveSupport::JSON.decode can understand
"{\"users\": [{\"user_id\": 1,\"name\": \"Chris Rivers\"},{\"user_id\": 3,\"name\": \"Peter Curley\"}]}"
you'll see there is no issue iterating over each object in "users" (x below is the above JSON string)
[8] pry(main)> ActiveSupport::JSON.decode(x)["users"].map { |user| user["name"] }
=> ["Chris Rivers", "Peter Curley"]
Does your source data actually have the trailing commas after each user's name? I get a parse error for that, but your code works as you want it to if I remove them:
json = '{ "users": [ { "user_id": 1, "name": "Chris Rivers" }, { "user_id": 3, "name": "Peter Curley" } ]}'
ActiveSupport::JSON.decode(json)["users"].each do |user|
puts user["name"]
end
The problem isn't not recognizing the array, it's the trailing commas after the "name" elements.
Removing those allows JSON parsing to proceed normally:
pry(main)> ActiveSupport::JSON.decode(s)["users"]
=> [{"user_id" => 1, "name" => "Chris Rivers"},
{"user_id" => 3, "name" => "Peter Curley"}]

Correct JSON structure

I need to return a leaderboard data in pages via JSON, which is the correct structure, is it this
{
pages: [
{
[
{user: John,
rating:11},
{user: Bob,
rating: 20},
{user: Andy,
rating: 30},
...
]
},
{
[
{user: Sally,
rating: 110},
{user: Peter,
rating: 115},
{user: Jim,
rating: 350},
...
]
},
...
]
}
Or is this (correct JSON)
{
"pages": [
[
{
"user": "John",
"rating": 11
},
{
"user": "Bob",
"rating": 20
},
{
"user": "Andy",
"rating": 30
}
],
[
{
"user": "Sally",
"rating": 110
},
{
"user": "Peter",
"rating": 115
},
{
"user": "Jim",
"rating": 350
}
]
]
}
UPDATE:
Thanks for all the prompt answers, and yes I did construct the JSON by hand which is obviously not a good idea as some of you have pointed out. The 2nd option is the proper JSON and I have updated it with the correct JSON structure for anyone else that might be reading this in the future.
The latter is correct, but you need to enclose all your strings with double quotes. You also used a period instead of a comma after the first closing square bracket.
You may wish to use JSONLint to validate your JSON.
Your first example doesn’t make much sense: pages is an array whose elements are objects but there are no key-value pairs. Your second example makes more sense: pages is an array where which element is in turn another array containing a list of objects.
Note that neither of your examples is valid JSON. As explained in the previous paragraph, your first example has objects with no key-value pairs. Furthermore, in both examples the strings aren’t quoted. In JSON, every string must be quoted, be it a key or a value.
You might want to check out this JSON validator :) http://www.jsonlint.com/
For starters, the first option is not valid JSON. The array:
{
pages: [
{
[ <== HERE
...would require a name. E.g.
{
pages: [
{
"SomeName": [
Also, assuming John, Bob, Andy etc, are strings, then they should be:
[
{user: "John",
rating:11},
{user: "Bob",
rating: 20},
{user: "Andy",
rating: 30},
...
]
Some would also argue that your dictionary member names should be enquoted.

Resources