如何使用JSON进行Ruby对象序列化
我有这样一个简单容器类的结构(在伪ruby中): 有没有简单的方法在Ruby中将其反序列化为JSON?或者我应该像中那样为每个类创建嵌套的序列化方法 编辑: 在我的特定场景中,我想将一些JSON数据发布到运行Ruby的服务器上,该服务器将提取数据并相应地执行操作 JSON的发送方不一定是Ruby进程,但可能是其他系统的后端。(尽管在我的测试工具中它是Ruby) 因此,我不需要JSON是某种“特定于Ruby”的格式,我只是假设它实际上内置于Ruby中会更容易。对非JSON对象使用Marshal、PStore或其他Ruby解决方案 人们可能有理由怀疑,为什么像Ruby这样的完全反射式语言不能自动生成JSON并解析任意类 但是,除非您坚持使用JSON类型,否则除了发送或接收另一个正在运行的Ruby之外,没有其他地方可以发送或接收JSON对象。在这种情况下,我怀疑传统的智慧是“忘记JSON,使用原生Ruby接口,比如核心类如何使用JSON进行Ruby对象序列化,ruby,serialization,json,Ruby,Serialization,Json,我有这样一个简单容器类的结构(在伪ruby中): 有没有简单的方法在Ruby中将其反序列化为JSON?或者我应该像中那样为每个类创建嵌套的序列化方法 编辑: 在我的特定场景中,我想将一些JSON数据发布到运行Ruby的服务器上,该服务器将提取数据并相应地执行操作 JSON的发送方不一定是Ruby进程,但可能是其他系统的后端。(尽管在我的测试工具中它是Ruby) 因此,我不需要JSON是某种“特定于Ruby”的格式,我只是假设它实际上内置于Ruby中会更容易。对非JSON对象使用Marshal、P
Marshal
”
因此,如果您真的要将这些对象发送到PHP或其他非Ruby的对象,那么您应该使用Array等直接创建支持JSON的Ruby数据结构,然后JSON.generate将直接处理这些数据结构
如果只需要序列化,可以使用marshall
或PStore
更新:啊哈,好的,试试这个:
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
如果您在每个类中包含AutoJ,那么它应该是DTRT
{
"a": {
"string_field1": "aa",
"string_field2": "bb"
},
"b": {
"int_field3": 123,
"string_field4": "dd"
}
}
您可能希望将auto_j
方法更改为返回h.values
,而不仅仅是h
,在这种情况下,您会得到:
[
["aa", "bb"],
[123, "dd"]
]
我也有同样的问题(主要是试图创建任意复杂度的JSON字符串),而不是解析它们并将其封送为JSON字符串,我最终编写了自己的简单序列化程序。此代码还转义特殊字符以创建有效的JSON
你所要做的就是:
json = JSON.new;
jsonString = json.marshal(obj); # Where obj is a Ruby object
下面是我为自定义类实现json的方法 在模块中使用
self.include
有一点神奇。这是2006年的一篇非常好的文章,介绍了模块同时具有实例和类方法
该模块设计为包含在任何类中,以提供to_json
功能。它拦截attr_accessor
方法,而不是使用自己的方法,以便对现有类进行最小的更改
to_json
实现就是基于此
谢谢,请参阅我的说明。我当时的印象是,封送闭包会比当前更加自动化。只需小心封送闭包,如
lambdas
或Procs
。它们不能。我不知道这是否是一个广泛的列表,可能还有其他结构无法封送。
json = JSON.new;
jsonString = json.marshal(obj); # Where obj is a Ruby object
module JSONable
module ClassMethods
attr_accessor :attributes
def attr_accessor *attrs
self.attributes = Array attrs
super
end
end
def self.included(base)
base.extend(ClassMethods)
end
def as_json options = {}
serialized = Hash.new
self.class.attributes.each do |attribute|
serialized[attribute] = self.public_send attribute
end
serialized
end
def to_json *a
as_json.to_json *a
end
end
class CustomClass
include JSONable
attr_accessor :b, :c
def initialize b: nil, c: nil
self.b, self.c = b, c
end
end
a = CustomClass.new(b: "q", c: 23)
puts JSON.pretty_generate a
{
"b": "q",
"c": 23
}