Ruby-объекты и JSON-сериализация (без Rails)
Я пытаюсь понять ландшафт сериализации JSON в Ruby. Я новичок в Руби.
Есть ли хорошие варианты сериализации JSON, если вы не работаете с Rails?
Кажется, именно в этом заключается ответ (на Rails). Как преобразовать объект Ruby в JSON.
Похоже, что с помощью json gem вам нужно написать собственный метод to_json. Я не смог заставить to_json работать с массивами и хэшами (в документации сказано, что он работает с ними). Есть ли причина, по которой гем json не просто отражает объект и использует стратегию сериализации по умолчанию? Разве не так to_yaml работает (догадываясь здесь)
12 ответов
Чтобы библиотека 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 создаст что-то вроде "\"#<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
сериализовать в JSON и object.from_json! string
скопировать сохраненное состояние, которое было сохранено в виде строки JSON, в объект.
Проверьте 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"
}
Какую версию Ruby вы используете? ruby -v
скажу тебе.
Если это 1.9.2, JSON включен в стандартную библиотеку.
Если ты на 1.8.что то делай gem install json
и он установит. Затем в вашем коде сделайте:
require 'rubygems'
require 'json'
Затем добавить to_json
на объект, и вы готовы идти:
asdf = {'a' => 'b'} #=> {"a"=>"b"}
asdf.to_json #=> "{"a":"b"}"
Так как я много искал, чтобы сериализовать Ruby Object в 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}
require 'json'
{"foo" => "bar"}.to_json
# => "{\"foo\":\"bar\"}"
Если вы используете 1.9.2 или выше, вы можете конвертировать хэши и массивы во вложенные объекты JSON, просто используя to_json.
{a: [1,2,3], b: 4}.to_json
В Rails вы можете вызывать to_json для объектов Active Record. Вы можете передать: include и: only параметры для управления выводом:
@user.to_json only: [:name, :email]
Вы также можете вызвать to_json для отношений AR, вот так:
User.order("id DESC").limit(10).to_json
Вам не нужно ничего импортировать, и все работает точно так, как вы надеетесь.
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\"}"
Чтобы получить сборку в классах (таких как Array и Hash) для поддержки as_json
а также to_json
, вам нужно require 'json/add/core'
(подробности см. в файле readme)
Старый поток, но все еще законный вопрос. Я лично был разочарован параметрами сериализации в ruby, особенно зная, насколько медленным это может быть из-за драгоценных камней, не учитывающих распределение памяти. Я использовал их все эти годы.
Я создал undraper-serializer и использовал его в коммерческих условиях с общедоступными API большого объема с потенциалом возврата 10 МБ JSON. Основные преимущества этого камня:
- Очень быстро
- Разрешить выбор полей для возврата (возможность выбора, аналогичная GraphQL)
- Полууверенный, чтобы контролировать естественное возникновение в больших базах кода, чтобы добавлять и изменять так много, что вывод становится прожорливым
- HATEOAS, который легко сделать (и необязательно)
На самом деле, существует камень под названием Jsonable, https://github.com/treeder/jsonable. Это довольно мило.
Раньше я virtus
, Действительно мощный инструмент, позволяющий создать динамическую структуру структуры Ruby на основе заданных вами классов. Легкий DSL, возможно создание объектов из рубиновых хэшей, есть строгий режим. Проверьте это.