一尘不染

如何使用JSON进行Ruby对象序列化

json

我有一个像这样的简单容器类的结构(在伪红宝石中):

class A
  attr_reader :string_field1, :string_field2
  ...
end

class B
  attr_reader: int_field3, :string_field4
  ...
end

# C includes an instance of A and B
class C
  attr_reader: :a_instance, :b_instance
  ...
end

有没有简单的方法可以在Ruby中将其反序列化为JSON?还是应该像本例一样为每个类制作嵌套的序列化方法?

编辑:

在我的特定情况下,我想将一些JSON数据发布到运行Ruby的服务器上,该服务器将提取数据并采取相应的措施。

JSON的发送者不一定是Ruby进程,而可能是其他系统的后端。(尽管在我的测试工具中是Ruby)。

因此,我不需要JSON采用某种“特定于Ruby的”格式,我只是假设如果将其实际内置于Ruby中会更容易。


阅读 395

收藏
2020-07-27

共1个答案

一尘不染

将Marshal,PStore或其他Ruby解决方案用于非JSON对象

有人可能会奇怪,为什么像Ruby这样的完全反射性语言不能自动执行JSON生成和任意类的解析。

但是,除非坚持使用JSON类型,否则除了发送给其他正在运行的Ruby之外,没有其他地方可以发送或接收JSON对象。在那种情况下,我怀疑传统的看法是“忘记JSON,使用像核心类这样的本地Ruby接口Marshal

因此,如果您确实要将这些对象发送到PHP或非Ruby的对象,则应该使用Array等直接创建支持JSON的Ruby数据结构,然后使用JSON.generate直接处理这些对象。

如果只需要序列化,则可以使用MarshalPStore

更新:啊哈,好的,试试这个:

module AutoJ
  def auto_j
    h = {}
    instance_variables.each do |e|
      o = instance_variable_get e.to_sym
      h[e[1..-1]] = (o.respond_to? :auto_j) ? o.auto_j : o;
    end
    h
  end
  def to_json *a
    auto_j.to_json *a
  end
end

如果然后您include AutoJ在每个班级中都应该使用DTRT。在您的示例中,这导致

{
  "a": {
    "string_field1": "aa",
    "string_field2": "bb"
  },
  "b": {
    "int_field3": 123,
    "string_field4": "dd"
  }
}

您可能希望将auto_j方法更改为return h.values而不是just h,在这种情况下,您将获得:

[
  ["aa", "bb"],
  [123, "dd"]
]
2020-07-27