当包含其他嵌套的类对象(不使用Rails或Active Support)时,将Ruby类对象转换为JSON并返回JSON

时间:2018-06-20 18:23:51

标签: json ruby

在为类编写自定义to_jsonfrom_json方法时,我感到很困惑。我实际上已经找到了解决方案,但是不知道为什么会起作用,也不知道为什么我最初的尝试不起作用。

我有一个People类,该类通过将Person类的实例作为参数来初始化。
Person中的to_json / from_json方法已从通用复制 外部模块,因此有点罗...……但是当我在Person对象的单个实例上对其进行测试时,它可以工作。

从JSON重新创建People对象时出现问题。对于@person实例变量,我期望:

#<Person:0x00000001a0b440 @name="Jon", @age=22, @gender="male">

相反,我将@person作为数组(因此,只有键):

#<People:0x00000001b5c038 @person=["@name", "@age", "@gender"]>

完整代码如下:

require "json"

class Person

  attr_accessor :name, :age, :gender

  def initialize(name, age, gender)
    @name = name
    @age = age
    @gender = gender
  end

  def to_json
    obj = {}
    instance_variables.map do |var|
      obj[var] = instance_variable_get(var)
    end
    JSON.dump(obj)
  end

  def from_json(string)
    obj = JSON.parse(string)
    obj.keys.each do |key|
      instance_variable_set(key, obj[key])
    end
  end

end

class People

  attr_accessor :person

  def initialize(person)
    @person = person
  end

  def to_json
    obj = {}
    obj[:person] = @person.to_json
    JSON.dump(obj)
  end

  def from_json(string)
    obj = JSON.parse(string, {:symbolize_names => true})
    person = Person.new("", 0, "")
    @person = person.from_json(obj[:person])
  end

  def <<(person)
    @persons << person
  end

end

在重新编写如下的to_jsonfrom_json方法之后,问题似乎已经解决了……现在可以按预期正确地重新组装@person了。

def to_json
  obj = {}
  obj[:persons] = [@person.to_json]
  JSON.dump(obj)
end

def from_json(string)
  obj = JSON.parse(string, {:symbolize_names => true})
  persons = []
  obj[:persons].each do |person_string|
    person = Person.new("", 0, "")
    person.from_json(person_string)
    persons << person
  end
  @person = persons[0]
end 

我很高兴找到一个解决方案,但是我不明白为什么将单个Person对象封装在数组中可以解决这种情况。

我敢肯定还有很多其他方法可以解决这种特殊情况(以及其他方法完全...例如:其他宝石,或使用Rails Active Support ...),但是我只是想尝试更多方法扎实的理解为什么我的最初想法不起作用...在事态变得更加复杂时为以后提供帮助。

感谢您提供的任何帮助...

1 个答案:

答案 0 :(得分:0)

您的第一个解决方案有效。您只是忘记了从方法中返回。见下文:

$postsWithTags = Post::with(‘tags’)->get();

在第二个解决方案中,您仍然缺少返回值,但是Ruby隐式地从方法中返回最后一个求值的表达式,而该表达式恰好是正确的。这就是您的第一个解决方案不起作用的原因。