Ruby对象和JSON序列化(无Rails)


70

我正在尝试了解Ruby中的JSON序列化格局。我是Ruby的新手。

如果您不使用Rails,是否有任何好的JSON序列化选项?

这似乎是(Rails的)答案的出路 如何将Ruby对象转换为JSON

json gem似乎使您看起来必须编写自己的to_json方法。我还无法使to_json与数组和哈希一起使用(文档说可以与它们一起使用)难道是json gem不能仅仅反映对象并使用默认序列化策略的原因吗?这不是to_yaml的工作原理(在这里猜测)


2
听起来可能很愚蠢,但是您真的require 'json'吗?我使用JSON宝石,它们像魅力一样工作。
DarkDust 2010年

Answers:


111

为了使JSON库可用,您可能必须libjson-ruby从程序包管理器进行安装。

要使用“ json”库:

require 'json'

要将对象转换为JSON(这三种方式等效):

JSON.dump object #returns a JSON string
JSON.generate object #returns a JSON string
object.to_json #returns a JSON string

要将JSON文本转换为对象(这两种方法是等效的):

JSON.load string #returns an object
JSON.parse string #returns an object

对于您自己类中的对象,这将变得有些困难。对于以下类,to_json将产生类似的信息"\"#<A:0xb76e5728>\""

class A
    def initialize a=[1,2,3], b='hello'
        @a = a
        @b = b
    end
end

这可能是不可取的。为了将您的对象有效地序列化为JSON,您应该创建自己的to_json方法。为此,from_json类方法将很有用。您可以像这样扩展您的课程:

class A
    def to_json
        {'a' => @a, 'b' => @b}.to_json
    end
    def self.from_json string
        data = JSON.load string
        self.new data['a'], data['b']
    end
end

您可以通过从“ JSONable”类继承来实现此自动化:

class JSONable
    def to_json
        hash = {}
        self.instance_variables.each do |var|
            hash[var] = self.instance_variable_get var
        end
        hash.to_json
    end
    def from_json! string
        JSON.load(string).each do |var, val|
            self.instance_variable_set var, val
        end
    end
end

然后,您可以用于object.to_json序列object.from_json! string化为JSON并将复制为JSON字符串的保存状态复制到该对象。


4
正在寻找不需要您在类上编写to_json方法的库。您是否可以继承一个类,通过反射将其提供给您?并能处理复杂的物体?
BuddyJoe 2010年

1
你们确定没有更简单的方法吗?
jj_ 2012年

4
要从属性名称中删除@,请执行以下操作:hash [var.to_s.delete“ @”]
epzee 2012年

6
这行不通:in `to_json': wrong number of arguments (1 for 0) (ArgumentError)
散发2014年

2
@redolent-看起来很糟糕。用于to_json(options={})修复。看到stackoverflow.com/questions/11599610/...
兰德尔

11

Oj。将任何旧对象转换为JSON都有些麻烦,但是Oj可以做到。

require 'oj'

class A
    def initialize a=[1,2,3], b='hello'
        @a = a
        @b = b
    end
end

a = A.new
puts Oj::dump a, :indent => 2

输出:

{
  "^o":"A",
  "a":[
    1,
    2,
    3
  ],
 "b":"hello"
}

请注意,^o它用于指定对象的类,并且在那里有助于反序列化。要省略^o,请使用:compat模式:

puts Oj::dump a, :indent => 2, :mode => :compat

输出:

{
  "a":[
    1,
    2,
    3
  ],
  "b":"hello"
}

Oj与更改类和反序列化它们具有极大的兼容性,而不会产生其他错误。+1
ashes999

1
如何删除此“ ^ oj”值?
neustart47 '16

1
@ neustart47:我已经编辑了答案,以显示如何使用:compat模式完成此操作。
Jimothy '16

8

如果渲染性能至关重要,则可能还需要查看yajl-ruby,它是对C yajl库的绑定。那个的序列化API看起来像:

require 'yajl'
Yajl::Encoder.encode({"foo" => "bar"}) #=> "{\"foo\":\"bar\"}"

由于在下一个项目中我将不得不处理大量JSON数据,因此可以节省很多时间。+1
欧内斯特(Ernest)2010年

7

您正在使用哪个版本的Ruby?ruby -v会告诉你。

如果为1.9.2,则标准库中包含JSON

如果您使用的是1.8.something,请gem install json安装并安装。然后,在您的代码中执行:

require 'rubygems'
require 'json'

然后附加to_json到一个对象,您就可以开始:

asdf = {'a' => 'b'} #=> {"a"=>"b"}
asdf.to_json #=> "{"a":"b"}"

它会比yajl更快吗?
欧内斯特(Ernest)2010年

那是供您确定使用的Benchmark,不是吗?
Tin Man 2010年

1
我以为你也许知道这一点。基准测试,速度慢:P特别是在编码时。
欧内斯特(Ernest)2010年

7

由于我自己进行了大量搜索,以将Ruby对象序列化为json:

require 'json'

class User
  attr_accessor :name, :age

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

  def as_json(options={})
    {
      name: @name,
      age: @age
    }
  end

  def to_json(*options)
    as_json(*options).to_json(*options)
  end
end

user = User.new("Foo Bar", 42)
puts user.to_json #=> {"name":"Foo Bar","age":42}

1
我将其复制/粘贴到ruby文件中,并且执行起来没有问题。更新您的答案以包括以下输出可能会有所帮助:{“ name”:“ Foo Bar”,“ age”:42}
Matthew Kraus


1

如果您使用的是1.9.2或更高版本,则可以仅使用to_json将哈希和数组转换为嵌套的JSON对象。

{a: [1,2,3], b: 4}.to_json

在Rails中,可以在Active Record对象上调用to_json。您可以传递:include和:only参数来控制输出:

@user.to_json only: [:name, :email]

您也可以在AR关系上调用to_json,如下所示:

User.order("id DESC").limit(10).to_json

您不需要导入任何东西,并且一切都可以按照您希望的那样进行。



1

Jbuilder是Rails社区构建的瑰宝。但是它在非铁路环境中运行良好,并且具有很酷的功能。

# suppose we have a sample object as below
sampleObj.name #=> foo
sampleObj.last_name #=> bar

# using jbuilder we can convert it to json:
Jbuilder.encode do |json|
  json.name sampleObj.name
  json.last_name sampleObj.last_name
end #=> "{:\"name\" => \"foo\", :\"last_name\" => \"bar\"}"

0

实际上,有一个名为Jsonable的宝石,https://github.com/treeder/jsonable。很甜


Jsonable似乎已失效:最后一次更新于2012年,示例代码失败-JSON.parse返回json,而不是对象。
ashes999 2014年


也许这取决于Rails或其他东西。我正在使用纯Ruby。
ashes999 2014年

我也是,不使用Rails。
dentarg 2014年

0

我曾经virtus。真正强大的工具,可用于根据您指定的类创建动态Ruby结构。简单的DSL,可以从红宝石哈希创建对象,有严格的模式。看看

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.