Compare JSON structure in ruby - ruby-on-rails

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.

Related

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

Searching nested hash

These is sample response of hashes in ruby.
Eg:-
find abcd1234
should give me
i was able to find by but it's not sufficent
I have response of sth like these and list keep on going different value but same structure
[
{
"addon_service": {
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "heroku-postgresql"
},
"config_vars": [
"FOO",
"BAZ"
],
"created_at": "2012-01-01T12:00:00Z",
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "acme-inc-primary-database",
"plan": {
"id": "01234567-89ab-cdef-0123-456789abcdef",
"name": "heroku-postgresql:dev"
},
"app": {
"id"=>"342uo23iu4io23u4oi2u34",
"name"=>"heroku-staging"},
},
"provider_id": "abcd1234",
"updated_at": "2012-01-01T12:00:00Z",
"web_url": "https://postgres.heroku.com/databases/01234567-89ab-cdef-0123-456789abcdef"
} .........
]
can anyone know how to grab those?
You can iterate all array element (a hash) and display its content if the hash meet your requirement:
element_found = 0
YOUR_DATA.each do |element|
if element["provider_id"].match(/abcd1234/)
element_found += 1
puts "addon_service: #{element['addon_service']['name']}"
puts "app: #{element['app']['name']}"
end
end
if element_found == 0 puts "Sorry match didn't found"
Since the elements of the array are hashes you can select the appropriate ones by matching the desired key.
select {|app| app[:provider_id] == "abcd1234"}
Do you know what to do with the element once you select it?
I think you want some of the items from the hash, but not all of them.
That might look like:
select {|app| app[:provider_id] == "abcd1234"}.map {|app| app.select {|key, v| [:addon_service, :app].include?(key) } }

MagicalRecord map String array to object

I'm using MagicalRecord to import json object to Core Data. I have a list of persons with firstName and lastName attributes. This works fine. each person has a list of degrees that is a simple array of strings. I would like to map this list of string to my Degree core data entity and map the string to the e.g. Degree.name attribute
[
{
"firstName": "ba",
"lastName": "bar",
"degrees": [
"MSc",
"BSc"
]
},
{
"firstName": "Fo",
"lastName": "foo",
"degrees": [
"MSc"
]
}
]
I tried using a empty mappedKeyName on the name attribute as described here but it does not work.

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.

Output JSON array without the class name in every array element

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) ...

Resources