Mackaber
Mackaber

Reputation: 43

How to serialize a Sequel result into JSON

This is my Model

class Client < Sequel::Model(:clients)
end

When I execute

Client.first.to_json

I get

"\"#<Client:0x2594b824>\""

But when I execute

DB[:clients].first.to_json

I correctly get:

{id: 1, name: "Someone" ... }

What am I doing wrong?... I also tried using Client.dataset.first.json having the same result.

Also I'm using a MS Access DB but I don't think that's important.

Upvotes: 2

Views: 2220

Answers (2)

Kris
Kris

Reputation: 19948

The json library (part of the Ruby standard library), and other gems such as ActiveSupport, monkey patch objects with a to_json method which could be what is getting called, not a the specific to_json method supplied by Sequel which knows how to convert a Sequel::Model instance to JSON. This is speculation as I'd be surprised that the JSON library monkey patches anything other than String, Array, Hash etc.

When using DB[:clients].first you probably get back a Hash which has a to_json method, where as Client.first returns a model instance which isn't handled by the generic to_json method supplied by the json library.

Try registering the Sequel JSON plugin, this should take precedence over the monkey patched to_json method:

Sequel::Model.plugin :json_serializer

By the way this is a good indicator of why monkey patching is often a bad idea, particularly monkey patching of classes which are outside a libraries/gems namespace.

Upvotes: 5

the Tin Man
the Tin Man

Reputation: 160549

You need to use to_hash:

require 'json'
require 'sequel'

DB = Sequel.sqlite
DB.create_table :items do
  primary_key :id
  String :name
  Float :price
end
items = DB[:items]
items.insert(:name => 'abc', :price => rand * 100)

class Item < Sequel::Model(:items)
end

Item.first
  .to_hash # => {:id=>1, :name=>"abc", :price=>51.47074347440235}
  .to_json # => "{\"id\":1,\"name\":\"abc\",\"price\":51.47074347440235}"

Upvotes: 4

Related Questions