2015-02-04 29 views
6

Tôi đang cố gắng tuần tự hóa một cấu trúc đơn giản để JSON hoạt động tốt, nhưng tôi không thể tạo ra một cá thể của cấu trúc đó từ JSON. Đây là cách tôi đang cố gắng làm điều đó.Cấu trúc tuần tự hóa Ruby với JSON

require 'rubygems' 
require 'json' 

Person = Struct.new(:name, :age) 

json = Person.new('Adam', 19).to_json 
puts json 

me = JSON.load(json) 
puts me.name 

Và tôi nhận được kết quả như sau:

"#<struct Person name=\"Adam\", age=19>" 
/usr/lib/ruby/1.9.1/json/common.rb:148:in `parse': 746: unexpected token at '"#<struct Person name=\"Adam\", age=19>"' (JSON::ParserError) 
    from /usr/lib/ruby/1.9.1/json/common.rb:148:in `parse' 
    from /usr/lib/ruby/1.9.1/json/common.rb:309:in `load' 
    from why.rb:9:in `<main>' 

Trả lời

10

Trong trường hợp này, person.to_json không làm những gì bạn mong đợi.

Khi bạn require 'json', thư viện JSON chèn một phương pháp #to_json trên Object đó là dự phòng nếu không có phương thức chuyên biệt #to_json được cung cấp ở nơi khác. This inserted method về cơ bản giống như gọi số #to_s#to_json trên một đối tượng.

Trong trường hợp của lớp Person ở đây, #to_s kết quả đầu ra là standard Object#to_s, theo mặc định, không cung cấp chuỗi có thể phân tích cú pháp bằng thư viện JSON.

Tuy nhiên, Structkhông cung cấp một phương pháp #to_h có thể được sử dụng để chuyển đổi struct đó để một Hash, và Hash là (theo yêu cầu thư viện JSON) biết làm thế nào để tạo ra một sản lượng JSON parseable.

Vì vậy, chỉ đơn giản là thay đổi:

json = Person.new('Adam', 19).to_json 
puts json 

tới:

person = Person.new('Adam', 19) 
puts person.to_h.to_json 

sẽ làm những gì bạn mong đợi.

(An sang một bên, tôi thực sự muốn giới thiệu thực hiện #to_json trên lớp Person trực tiếp như gọi #to_h#to_json vi phạm Law of Demeter.)

+1

Cảm ơn mà làm việc một cách hoàn hảo. Tôi chỉ muốn lưu ý cho bất cứ ai đọc điều này trong tương lai rằng phương pháp to_h đã được thêm vào trong ruby ​​2.0, vì vậy nếu bạn đang sử dụng 1.9.3 như tôi là bạn sẽ phải nâng cấp. –

Các vấn đề liên quan