44

I looked into different resources and still get confused on how to parse a json format to a custom object, for example

class Resident
  attr_accessor :phone, :addr

  def initialize(phone, addr)
      @phone = phone
      @addr = addr
  end
end    

and JSON file

{
  "Resident": [
    {
      "phone": "12345",
      "addr":  "xxxxx"
    }, {
      "phone": "12345",
      "addr": "xxxxx"
    }, {
      "phone": "12345",
      "addr": "xxxxx"
    }
  ]
}

what's the correct way to parse the json file into a array of 3 Resident object?

4
  • 2
    Parse this JSON into a ruby hash, then walk that hash and create Resident objects. Commented Oct 4, 2012 at 8:21
  • @SergioTulentsev is that by using JSON.parse(jsonfile) ? Commented Oct 4, 2012 at 8:27
  • @SergioTulentsev Thanks I got that part but how to fit in new object? Is it using class_variable_defined or something else? Commented Oct 4, 2012 at 8:35
  • Just a note to say that you need to remove the trailing comma after the "xxxxx" , else JSON will complain. Commented Oct 4, 2012 at 8:42

5 Answers 5

111

Today i was looking for something that converts json to an object, and this works like a charm:

person = JSON.parse(json_string, object_class: OpenStruct)

This way you could do person.education.school or person[0].education.school if the response is an array

I'm leaving it here because might be useful for someone

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

2 Comments

imho the best way to do it.
Convenient, but not a custom object.
42

The following code is more simple:

require 'json'

data = JSON.parse(json_data)
residents = data['Resident'].map { |rd| Resident.new(rd['phone'], rd['addr']) }

Comments

13

If you're using ActiveModel::Serializers::JSON you can just call from_json(json) and your object will be mapped with those values.

class Person
  include ActiveModel::Serializers::JSON

  attr_accessor :name, :age, :awesome

  def attributes=(hash)
    hash.each do |key, value|
      send("#{key}=", value)
    end
  end

  def attributes
    instance_values
  end
end

json = {name: 'bob', age: 22, awesome: true}.to_json
person = Person.new
person.from_json(json) # => #<Person:0x007fec5e7a0088 @age=22, @awesome=true, @name="bob">
person.name # => "bob"
person.age # => 22
person.awesome # => true

Comments

4
require 'json'

class Resident
    attr_accessor :phone, :addr

    def initialize(phone, addr)
        @phone = phone
        @addr = addr
    end
end

s = '{"Resident":[{"phone":"12345","addr":"xxxxx"},{"phone":"12345","addr":"xxxxx"},{"phone":"12345","addr":"xxxxx"}]}'

j = JSON.parse(s)

objects = j['Resident'].inject([]) { |o,d| o << Resident.new( d['phone'], d['addr'] ) }

p objects[0].phone
"12345"

2 Comments

That's not bad, but you could use the Enumerable#map instead of each.
I added my idea as an answer.
3

We recently released a Ruby library static_struct that solves the issue. Check it out.

Comments

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.