非常教程

Ruby 2.4参考手册

编排 | Marshal

Marshal

编组库将 Ruby 对象的集合转换为字节流,允许它们存储在当前活动脚本之外。随后可以读取该数据并重建原始对象。

封送的数据与对象信息一起存储有主版本号和次版本号。在正常使用中,封送处理只能加载使用相同主要版本号和等同或较低次要版本号编写的数据。如果设置了 Ruby 的“详细”标志(通常使用-d,-v,-w 或 -verbose),则主要和次要数字必须完全匹配。元帅版本控制独立于 Ruby 的版本号。您可以通过阅读编组数据的前两个字节来提取版本。

str = Marshal.dump("thing")
RUBY_VERSION   #=> "1.9.0"
str[0].ord     #=> 4
str[1].ord     #=> 8

某些对象不能转储:如果要转储的对象包含绑定,过程或方法对象,类 IO 实例或单例对象,则会引发 TypeError。

如果您的类有特殊的序列化需求(例如,如果您想以某种特定格式序列化),或者如果它包含否则不可序列化的对象,则可以实现自己的序列化策略。

有两种方法可以做到这一点,你的对象可以定义 marshal_dump 和 marshal_load 或_dumpt和_load。如果两者都定义,marshal_dump 将优先于t_dump。marshal_dump 可能会导致较小的元帅字符串。

安全考虑

按照设计,:: load 可以反序列化几乎所有加载到 Ruby 进程中的类。在很多情况下,如果 Marshal 数据是从不可信源加载的,这可能会导致远程代码执行。

因此,:: load 不适合作为通用序列化格式,并且您不应该解组用户提供的输入或其他不可信数据。

如果您需要反序列化不可信数据,请使用tJSON或另一种只能加载简单的“原始”类型(例如tString,Array,Hash 等)的序列化格式。切勿允许用户输入指定要反序列化的任意类型。

marshal_dump and marshal_load

转储对象时,marshal_dump 方法将被调用。marshal_dump 必须返回包含 marshal_load 重构对象所需信息的结果。结果可以是任何对象。

当使用 marshal_dump 加载转储的对象时,首先分配对象,然后使用 marshal_dump 的结果调用 marshal_load。marshal_load 必须从结果中的信息中重新创建对象。

Example:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def marshal_dump
    [@name, @version]
  end

  def marshal_load array
    @name, @version = array
  end
end

_dump and _load

当你需要分配你正在恢复的对象时,使用 _dump 和 _load。

转储对象时,将使用 Integer 调用实例方法 _dump, Integer 指示要转储的对象的最大深度(值为-1意味着应禁用深度检查)。_dump 必须返回一个包含重构对象所需信息的 String。

类方法 _load 应该接受一个 String 并用它返回同一个类的对象。

例:

class MyObj
  def initialize name, version, data
    @name    = name
    @version = version
    @data    = data
  end

  def _dump level
    [@name, @version].join ':'
  end

  def self._load args
    new(*args.split(':'))
  end
end

因为:: dump 会输出一个字符串,所以你可以让_dump 返回一个在 _load 中为 Marshal.loaded 的 Marshal 字符串作为复杂对象。

常量

MAJOR_VERSION

主要版本

MINOR_VERSION

次要版本

公共类方法

dump( obj , anIO , limit=-1 ) → anIO Show source

序列化 obj 和所有后代对象。如果指定了 anIO,则会将序列化的数据写入该数据,否则数据将以字符串形式返回。如果指定了限制,子对象的遍历将被限制在该深度。如果限制为负值,则不会执行深度检查。

class Klass
  def initialize(str)
    @str = str
  end
  def say_hello
    @str
  end
end

(不产生输出)

o = Klass.new("hello\n")
data = Marshal.dump(o)
obj = Marshal.load(data)
obj.say_hello  #=> "hello\n"

Marshal 不能转储下列对象:

  • 匿名类/模块。
  • 与系统相关的对象(例如:Dir,File :: Stat,IO,File,Socket 等)
  • MatchData,Data,Method,UnboundMethod,Proc,Thread,ThreadGroup,Continuation 的一个实例
  • 定义单例方法的对象
static VALUE
marshal_dump(int argc, VALUE *argv)
{
    VALUE obj, port, a1, a2;
    int limit = -1;

    port = Qnil;
    rb_scan_args(argc, argv, "12", &obj, &a1, &a2);
    if (argc == 3) {
        if (!NIL_P(a2)) limit = NUM2INT(a2);
        if (NIL_P(a1)) io_needed();
        port = a1;
    }
    else if (argc == 2) {
        if (FIXNUM_P(a1)) limit = FIX2INT(a1);
        else if (NIL_P(a1)) io_needed();
        else port = a1;
    }
    return rb_marshal_dump_limited(obj, port, limit);
}

load( source , proc ) → obj Show source

返回将源代码中的序列化数据转换为 Ruby 对象(可能带有关联的从属对象)的结果。源可能是 IO 的一个实例或响应 to_str 的对象。如果指定了 proc,每个对象都将被传递给 proc,因为对象正在被反序列化。

切勿将不可信的数据(包括用户提供的输入)传递给此方法。请参阅概述了解更多详情。

static VALUE
marshal_load(int argc, VALUE *argv)
{
    VALUE port, proc;

    rb_check_arity(argc, 1, 2);
    port = argv[0];
    proc = argc > 1 ? argv[1] : Qnil;
    return rb_marshal_load_with_proc(port, proc);
}

restore( source , proc ) → obj Show source

返回将源代码中的序列化数据转换为 Ruby 对象(可能带有关联的从属对象)的结果。源可能是IO 的一个实例或响应 to_str 的对象。如果指定了 proc,每个对象都将被传递给 proc,因为对象正在被反序列化。

切勿将不可信的数据(包括用户提供的输入)传递给此方法。请参阅概述了解更多详情。

static VALUE
marshal_load(int argc, VALUE *argv)
{
    VALUE port, proc;

    rb_check_arity(argc, 1, 2);
    port = argv[0];
    proc = argc > 1 ? argv[1] : Qnil;
    return rb_marshal_load_with_proc(port, proc);
}

编排 | Marshal相关

Ruby 2.4

Ruby 是一种面向对象、命令式、函数式、动态的通用编程语言,是世界上最优美而巧妙的语言。

主页 https://www.ruby-lang.org/
源码 https://github.com/ruby/ruby
版本 2.4
发布版本 2.4.1

Ruby 2.4目录

1.缩略 | Abbrev
2.ARGF
3.数组 | Array
4.Base64
5.基本对象 | BasicObject
6.基准测试 | Benchmark
7.BigDecimal
8.绑定 | Binding
9.CGI
10.类 | Class
11.比较 | Comparable
12.负责 | Complex
13.计算续体 | Continuation
14.覆盖 | Coverage
15.CSV
16.日期 | Date
17.日期时间 | DateTime
18.DBM
19.代理 | Delegator
20.摘要 | Digest
21.Dir
22.DRb
23.编码 | Encoding
24.枚举 | Enumerable
25.枚举 | Enumerator
26.ENV
27.ERB
28.错误 | Errors
29.Etc
30.期望值 | Exception
31.错误类 | FalseClass
32.Fiber
33.Fiddle
34.文件 | File
35.文件实用程序 | FileUtils
36.查找 | Find
37.浮点 | Float
38.Forwardable
39.GC
40.GDBM
41.GetoptLong
42.Hash
43.Integer
44.IO
45.IPAddr
46.JSON
47.Kernel
48.语言 | 3Language
49.记录 | Logger
50.编排 | Marshal
51.MatchData
52.数学 | Math
53.矩阵 | Matrix
54.方法 | Method
55.模型 | Module
56.监控 | Monitor
57. 互斥 | Mutex
58.Net
59.Net::FTP
60.Net::HTTP
61.Net::IMAP
62.Net::SMTP
63.NilClass
64.数字 | Numeric
65.对象 | Object
66.ObjectSpace
67.Observable
68.Open3
69.OpenSSL
70.OpenStruct
71.OpenURI
72.OptionParser
73.路径名 | Pathname
74.完整输出 | PrettyPrint
75.Prime
76.Proc
77.过程 | Process
78.PStore
79.PTY
80.队列 | Queue
81.随机 | Random
82.范围 | Range
83.合理的 | Rational
84.Readline
85.Regexp
86.Resolv
87.Ripper
88.RubyVM
89.Scanf
90.SDBM
91.SecureRandom
92.Set
93.Shell
94.信号 | Signal
95.Singleton
96.套接字 | Socket
97.字符串 | String
98.StringIO
99.StringScanner
100.结构 | Struct