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

发布于 2024-10-07 20:11:06 字数 364 浏览 9 评论 0原文

我正在尝试了解 Ruby 中的 JSON 序列化环境。我是红宝石新手。

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

这似乎就是这个答案的去处(Rails) 如何将 Ruby 对象转换为 JSON

json gem 似乎为了让它看起来像你必须编写自己的 to_json 方法。 我无法让 to_json 处理数组和哈希(文档说它可以处理这些) json gem 不只反映对象并使用默认序列化策略是否有原因?这不是 to_yaml 的工作原理吗(这里猜测)

I'm trying to understand the JSON serialization landscape in Ruby. I'm new to Ruby.

Is there any good JSON serialization options if you are not working with Rails?

That seems to be where this answer goes (to Rails)
How to convert a Ruby object to JSON

The json gem seems to make it look like you have to write your own to_json method.
I haven't been able to get to_json to work with arrays and hashes (documentation says it works with these)
Is there a reason the json gem doesn't just reflect over the object and use a default serialization strategy? Isn't this how to_yaml works (guessing here)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(12

一人独醉 2024-10-14 20:11:06

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

使用 'json' 库:

require 'json'

将对象转换为 JSON(这 3 种方法是等效的):

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

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

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

对于您自己的类中的对象来说,这会有点困难。对于以下类,to_json 将生成类似 "\"#\"" 的内容。

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 序列化为 JSON 和 object.from_json! string 将保存为 JSON 字符串的保存状态复制到对象中。

For the JSON library to be available, you may have to install libjson-ruby from your package manager.

To use the 'json' library:

require 'json'

To convert an object to JSON (these 3 ways are equivalent):

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

To convert JSON text to an object (these 2 ways are equivalent):

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

It will be a bit more difficult for objects from your own classes. For the following class, to_json will produce something like "\"#<A:0xb76e5728>\"".

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

This probably isn't desirable. To effectively serialise your object as JSON, you should create your own to_json method. To go with this, a from_json class method would be useful. You could extend your class like so:

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

You could automate this by inheriting from a 'JSONable' class:

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

Then you can use object.to_json to serialise to JSON and object.from_json! string to copy the saved state that was saved as the JSON string to the object.

徒留西风 2024-10-14 20:11:06

查看 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"
}

Check out Oj. There are gotchas when it comes to converting any old object to JSON, but Oj can do it.

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

This outputs:

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

Note that ^o is used to designate the object's class, and is there to aid deserialization. To omit ^o, use :compat mode:

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

Output:

{
  "a":[
    1,
    2,
    3
  ],
  "b":"hello"
}
凯凯我们等你回来 2024-10-14 20:11:06

如果渲染性能至关重要,您可能还需要查看 yajl-ruby,它是一个绑定到 C yajl 库。该序列化 API 如下所示:

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

If rendering performance is critical, you might also want to look at yajl-ruby, which is a binding to the C yajl library. The serialization API for that one looks like:

require 'yajl'
Yajl::Encoder.encode({"foo" => "bar"}) #=> "{\"foo\":\"bar\"}"
鹤仙姿 2024-10-14 20:11:06

您使用什么版本的 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"}"

What version of Ruby are you using? ruby -v will tell you.

If it's 1.9.2, JSON is included in the standard library.

If you're on 1.8.something then do gem install json and it'll install. Then, in your code do:

require 'rubygems'
require 'json'

Then append to_json to an object and you're good to go:

asdf = {'a' => 'b'} #=> {"a"=>"b"}
asdf.to_json #=> "{"a":"b"}"
爱的故事 2024-10-14 20:11:06

因为我自己搜索了很多将 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}

Since I searched a lot myself to serialize a Ruby Object to 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}
向地狱狂奔 2024-10-14 20:11:06
require 'json'
{"foo" => "bar"}.to_json
# => "{\"foo\":\"bar\"}"
require 'json'
{"foo" => "bar"}.to_json
# => "{\"foo\":\"bar\"}"
撩起发的微风 2024-10-14 20:11:06

要让内置类(例如 Array 和 Hash)支持 as_jsonto_json,您需要 require 'json/add/core' (有关详细信息,请参阅自述文件

To get the build in classes (like Array and Hash) to support as_json and to_json, you need to require 'json/add/core' (see the readme for details)

没企图 2024-10-14 20:11:06

Jbuilder 是 Rails 社区构建的一个 gem。但它在非轨道环境中运行良好,并且具有一组很酷的功能。

# 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\"}"

Jbuilder is a gem built by rails community. But it works well in non-rails environments and have a cool set of features.

# 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\"}"
凌乱心跳 2024-10-14 20:11:06

老线程,但仍然是一个合理的问题。我个人对 ruby​​ 中的序列化选项感到失望,尤其是知道由于 gems 不考虑内存分配而导致它有多慢。多年来我一直在使用它们。

我构建了 undraper-serializer 并在商业环境中使用了它,具有大量公共 API,具有潜在的潜力返回 10 MB 的 JSON。这个 gem 的主要优点:

  • 非常快
  • 允许选择字段返回(类似于 GraphQL 的可选择性)
  • 半自以为是地控制大型代码库中的自然发生,添加和修改太多,以致于输出变得贪婪
  • HATEOAS 很容易做到(和可选)

Old thread but still a legitimate question to ask. I have personally been disappointed by serialization options in ruby especially knowing how slow it can be due to gems not considering memory allocations. I have used them all over the years.

I built undraper-serializer and have used this in commercial settings with high volume public APIs with the potential to return 10s of MBs of JSON. The primary advantages of this gem:

  • Very fast
  • Allow selection of fields to return (GraphQL-like selectability)
  • Semi opinionated to control the natural occurrence within large code bases to add and modify so much that the output becomes gluttonous
  • HATEOAS that is easy to do (and optional)
蔚蓝源自深海 2024-10-14 20:11:06

如果您使用的是 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

您不需要导入任何内容,一切都按照您希望的方式工作。

If you're using 1.9.2 or above, you can convert hashes and arrays to nested JSON objects just using to_json.

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

In Rails, you can call to_json on Active Record objects. You can pass :include and :only parameters to control the output:

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

You can also call to_json on AR relations, like so:

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

You don't need to import anything and it all works exactly as you'd hope.

隔岸观火 2024-10-14 20:11:06

实际上,有一个名为 Jsonable 的 gem,https://github.com/treeder/jsonable。非常甜蜜。

Actually, there is a gem called Jsonable, https://github.com/treeder/jsonable. It's pretty sweet.

ゞ记忆︶ㄣ 2024-10-14 20:11:06

我曾经使用virtus。真正强大的工具,允许根据您指定的类创建动态 Ruby 结构。 Easy DSL,可以从 ruby​​ 哈希创建对象,有严格模式。检查

I used to virtus. Really powerful tool, allows to create a dynamic Ruby structure structure based on your specified classes. Easy DSL, possible to create objects from ruby hashes, there is strict mode. Check it out.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文