Объекты Ruby и сериализация JSON (без Rails)

Я пытаюсь понять ландшафт сериализации JSON в Ruby. Я новичок в Ruby.

Есть ли хорошие варианты сериализации JSON, если вы не работаете с Rails?

Кажется, что этот ответ идет (к Rails) Как преобразовать объект Ruby в JSON

Кажется, что json gem выглядит так, будто вы должны написать свой собственный метод to_json. Мне не удалось заставить to_json работать с массивами и хешами (документация говорит, что он работает с ними) Есть ли причина, по которой json gem не просто отражает объект и использует стратегию сериализации по умолчанию? Разве это не так, как to_yaml работает (угадывая здесь)

Ответ 1

Чтобы библиотека 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 для сериализации в JSON и object.from_json! string для копирования сохраненного состояния, которое было сохранено в качестве строки JSON для объекта.

Ответ 2

Если производительность рендеринга имеет решающее значение, вы также можете посмотреть yajl-ruby, который является связыванием с C yajl. API-интерфейс сериализации для этого выглядит следующим образом:

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

Ответ 3

Проверьте 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"
}

Ответ 4

Какую версию 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"}"

Ответ 5

require 'json'
{"foo" => "bar"}.to_json
# => "{\"foo\":\"bar\"}"

Ответ 6

Поскольку я много раз искал, чтобы сериализовать 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}

Ответ 7

Если вы используете 1.9.2 или выше, вы можете конвертировать хеши и массивы в вложенные объекты JSON, используя to_json.

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

В Rails вы можете вызвать to_json в объектах Active Record. Вы можете передать: include и: только параметры для управления выходом:

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

Вы также можете вызвать to_json по отношениям AR, например:

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

Вам не нужно ничего импортировать, и все работает так, как вы надеетесь.

Ответ 8

Чтобы получить сборку в классах (например, Array и Hash) для поддержки as_json и to_json, вам нужно require 'json/add/core' (см. readme для деталей)

Ответ 9

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

Ответ 10

На самом деле есть драгоценный камень под названием Jsonable, https://github.com/treeder/jsonable. Это очень мило.

Ответ 11

Я использовал virtus. Действительно мощный инструмент, позволяет создавать динамическую структуру структуры Ruby на основе ваших указанных классов. Легкая DSL, возможность создания объектов из рубиновых хэшей, существует строгий режим. Проверьте it вне.