1

I have a json file. I am using it to store information, and as such it is constantly going to be both read and written.

I am completely new to ruby and oop in general, so I am sure I am going about this in a crazy way.

class Load
    def initialize(save_name)
    puts "loading " + save_name
        @data = JSON.parse(IO.read( $user_library + save_name ))
        @subject = @data["subject"]
        @id = @data["id"]
        @save_name = @data["save_name"]
        @listA = @data["listA"] # is an array containing dictionaries
        @listB = @data["listB"] # is an array containing dictionaries
        
    end
    attr_reader :data, :subject, :id, :save_name, :listA, :listB
end
 
example = Load.new("test.json")
puts example.id

=> 937489327389749

So I can now easily read the json file, but how could I write back to the file - refering to example? say I wanted to change the id example.id.change(7129371289)... or add dictionaries to lists A and B... Is this possible?

miken32
  • 42,008
  • 16
  • 111
  • 154
beoliver
  • 5,579
  • 5
  • 36
  • 72

1 Answers1

7

The simplest way to go to/from JSON is to just use the JSON library to transform your data as appropriate:

  • json = my_object.to_json — method on the specific object to create a JSON string.
  • json = JSON.generate(my_object) — create JSON string from object.
  • JSON.dump(my_object, someIO) — create a JSON string and write to a file.
  • my_object = JSON.parse(json) — create a Ruby object from a JSON string.
  • my_object = JSON.load(someIO) — create a Ruby object from a file.

Taken from this answer to another of your questions.

However, you could wrap this in a class if you wanted:

class JSONHash
  require 'json'
  def self.from(file)
    self.new.load(file)
  end
  def initialize(h={})
    @h=h
  end

  # Save this to disk, optionally specifying a new location
  def save(file=nil)
    @file = file if file
    File.open(@file,'w'){ |f| JSON.dump(@h, f) }
    self
  end

  # Discard all changes to the hash and replace with the information on disk
  def reload(file=nil)
    @file = file if file
    @h = JSON.parse(IO.read(@file))
    self
  end

  # Let our internal hash handle most methods, returning what it likes
  def method_missing(*a,&b)
    @h.send(*a,&b)
  end

  # But these methods normally return a Hash, so we re-wrap them in our class
  %w[ invert merge select ].each do |m|
    class_eval <<-ENDMETHOD
      def #{m}(*a,&b)
        self.class.new @h.send(#{m.inspect},*a,&b)
      end
    ENDMETHOD
  end

  def to_json
    @h.to_json
  end

end

The above behaves just like a hash, but you can use foo = JSONHash.from("foo.json") to load from disk, modify that hash as you would normally, and then just foo.save when you want to save out to disk.

Or, if you don't have a file on disk to begin with:

foo = JSONHash.new a:42, b:17, c:"whatever initial values you want"
foo.save 'foo.json'
# keep modifying foo
foo[:bar] = 52
f.save # saves to the last saved location
Community
  • 1
  • 1
Phrogz
  • 296,393
  • 112
  • 651
  • 745
  • Thanks, 2 days in a row :)... I have manage to get it working in a way that I think if people who knew what they are doing saw, would have a fit. I will however included it as an edit to my original question. – beoliver Jan 31 '12 at 17:05