如何在Psych中反序列化课程? [英] How do I deserialize classes in Psych?

查看:165
本文介绍了如何在Psych中反序列化课程?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我如何在Psych中反序列化以返回现有对象,例如类对象?

How do I deserialize in Psych to return an existing object, such as a class object?

要做一个类的序列化,我可以做

To do serialization of a class, I can do

require "psych"

class Class
  yaml_tag 'class'
  def encode_with coder
    coder.represent_scalar 'class', name
  end
end

yaml_string = Psych.dump(String) # => "--- !<class> String\n...\n" 

但是,如果我尝试对此进行Psych.load,则会得到一个匿名类,而不是String类.

but if I try doing Psych.load on that, I get an anonymous class, rather than the String class.

正常的反序列化方法是Object#init_with(coder),但这只会更改现有匿名类的状态,而我想要String类.

The normal deserialization method is Object#init_with(coder), but that only changes the state of the existing anonymous class, whereas I'm wanting the String class.

Psych::Visitors::ToRuby#visit_Psych_Nodes_Scalar(o)在某些情况下,不是使用init_with修改现有对象,而是确保首先创建正确的对象(例如,调用Complex(o.value)以反序列化复数),但是我不这样做.认为我不应该采用这种方法.

Psych::Visitors::ToRuby#visit_Psych_Nodes_Scalar(o) has cases where rather than modifying existing objects with init_with, they make sure the right object is created in the first place (for example, calling Complex(o.value) to deserialize a complex number), but I don't think I should be monkeypatching that method.

我注定要使用低水平或中等水平的发射,还是我错过了什么?

Am I doomed to working with low level or medium level emitting, or am I missing something?

背景

我将描述项目,为什么需要类以及为什么需要 (反序列化).

I'll describe the project, why it needs classes, and why it needs (de)serialization.

Small Eigen Collider旨在为Ruby创建随机任务以运行. 最初的目的是查看Ruby的不同实现是否 (例如Rubinius和JRuby)在给定时返回相同的结果 相同的随机任务,但我发现它也很适合 检测隔离Rubinius和YARV的方法.

The Small Eigen Collider aims to create random tasks for Ruby to run. The initial aim was to see if the different implementations of Ruby (for example, Rubinius and JRuby) returned the same results when given the same random tasks, but I've found that it's also good for detecting ways to segfault Rubinius and YARV.

每个任务都由以下内容组成:

Each task is composed of the following:

receiver.send(method_name, *parameters, &block)

其中,receiver是随机选择的对象,而method_name是 随机选择的方法的名称,*parameters是一个数组 随机选择的对象. &block不是很随机-基本上是 等同于{|o| o.inspect}.

where receiver is a randomly chosen object, and method_name is the name of a randomly chosen method, and *parameters is an array of randomly chosen objects. &block is not very random - it's basically equivalent to {|o| o.inspect}.

例如,如果接收者为"a",则method_name为:casecmp,并且 参数为["b"],那么您将要调用

For example, if receiver were "a", method_name was :casecmp, and parameters was ["b"], then you'd be calling

"a".send(:casecmp, "b") {|x| x.inspect}

等效于(因为该块无关)

which is equivalent to (since the block is irrelevant)

"a".casecmp("b")

Small Eigen Collider运行此代码,并记录这些输入和 也是返回值.在此示例中,大多数Ruby实现 返回-1,但在某一阶段,Rubinius返回+1. (我将其作为 错误 https://github.com/evanphx/rubinius/issues/518 和Rubinius 维护人员修复了该错误)

the Small Eigen Collider runs this code, and logs these inputs and also the return value. In this example, most implementations of Ruby return -1, but at one stage, Rubinius returned +1. (I filed this as a bug https://github.com/evanphx/rubinius/issues/518 and the Rubinius maintainers fixed the bug)

我希望能够在我的Small Eigen Collider中使用类对象. 通常,它们将是接收器,但它们也可能是其中之一 参数.

I want to be able to use class objects in my Small Eigen Collider. Typically, they would be the receiver, but they could also be one of the parameters.

例如,我发现进行段隔离YARV的一种方法是

For example, I found that one way to segfault YARV is to do

Thread.kill(nil)

在这种情况下,接收者是类对象Thread,而参数是 [零]. (错误报告: http://redmine.ruby-lang.org/issues/show/4367 )

In this case, receiver is the class object Thread, and parameters is [nil]. (Bug report: http://redmine.ruby-lang.org/issues/show/4367 )

小本征对撞机需要序列化的原因有两个.

The Small Eigen Collider needs serialization for a couple of reasons.

一个是使用随机数生成器生成一系列 每次都随机执行任务是不切实际的. JRuby具有不同的内置函数 随机数生成器,因此即使给定相同的PRNG种子,它也会 将不同的任务交给YARV.相反,我要做的是创建一个列表 随机任务一次(红宝石的第一次运行 bin/small_eigen_collider),将初始运行序列化列表 到task.yml的任务,然后随后运行 程序(使用不同的Ruby实现)在该task.yml中读取 文件以获取任务列表.

One is that using a random number generator to generate a series of random tasks every time isn't practical. JRuby has a different builtin random number generator, so even when given the same PRNG seed it'd give different tasks to YARV. Instead, what I do is I create a list of random tasks once (the first running of ruby bin/small_eigen_collider), have the initial running serialize the list of tasks to tasks.yml, and then have subsequent runnings of the program (using different Ruby implementations) read in that tasks.yml file to get the list of tasks.

我需要序列化的另一个原因是我希望能够进行编辑 任务列表.如果我的任务很长,导致 细分错误,我想将列表减少到所需的最低限度 导致分段错误.例如,出现以下错误 https://github.com/evanphx/rubinius/issues/643

Another reason I need serialization is that I want to be able to edit the list of tasks. If I have a long list of tasks that leads to a segmentation fault, I want to reduce the list to the minimum required to cause a segmentation fault. For example, with the following bug https://github.com/evanphx/rubinius/issues/643 ,

ObjectSpace.undefine_finalizer(:symbol)

本身不会引起分段错误,也不会造成

by itself doesn't cause a segmentation fault, and nor does

Symbol.all_symbols.inspect

但是如果将两者放在一起,就可以了.但是我从开始 数以千计的任务,并且需要将其减少到仅这两个 任务.

but if you put the two together, it did. But I started out with thousands of tasks, and needed to pare it back to just those two tasks.

反序列化返回现有的类对象是否有意义 在这种情况下,还是您认为有更好的方法?

Does deserialization returning existing class objects make sense in this context, or do you think there's a better way?

推荐答案

Psych维护人员已实现了模块.现在在Ruby中!

The Psych maintainer has implemented the serialization and deserialization of classes and modules. It's now in Ruby!

这篇关于如何在Psych中反序列化课程?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆