On Nov 29, 3:39 pm, george <[email protected]> wrote:
> when doing json deserializaion on sequel model objects, im seeing some
> strange effects. namely, a deserialized object looks like you did
> `ModelSubclass.new` and filled in column values without any checking
> or casting being done on their type.
That was an unintended consequence of the current implementation. I
agree that typecasting should be done by default, and will commit a
patch shortly that does this.
> for instance, accessing a date
> column will return a date string instead of a proper date class
> object. whats worse is that these newly deserialized objects cannot be
> modified and saved to cause the changes to be persisted to the
> database -- they throw an exception like "Sequel::DatabaseError:
> Mysql::Error: Duplicate entry '1' for key 1". these objects return
> true when '.new?' is called, and it appears to me that this value
> causes sequel to attempt an insert instead of an update when
> '.save_changes' is called (or something similar), thereby causing a
> primary key conflict. try the sample code below in irb for further
> clarification on these points.
The new flag was not copied over by design. Basically, the
json_serializer plugin considers incoming JSON untrustworthy, since it
often comes directly from client machines.
> i suppose what im really looking for is a clean way to have the
> deserialize step ('JSON.parse(foo)') optionally do stuff like
> typecasting of columns, updating to current values from the db, and
> setting of model instance flags (at least @new and perhaps
> @modified)... this could be done with options like 'JSON.parse(foo,
> {:typecast=>true, :autoRefresh=>false, :assumeNew=>true})'. i presume
> that it would be best to do typecasting by default, and NOT do
> the .refresh by default, but im not sure what would be best (in
> general) for the @new and @modified flags.
Your proposed API can't currently work, because the options hash given
to JSON.parse is not passed to the model's json_create method (https://
github.com/flori/json/blob/master/lib/json/pure/parser.rb#L296). I
would have definitely used an approach that used the JSON.parse
options hash if it was possible.
> what im doing now looks like this:
> deserializedModelObject = JSON.parse(serializedString).tap{|o|
> o.keys.each{|k| o[k]=o[k] }}.instance_ev...@new=@modified=false ;
> @changed_columns=[] ; self}
>
> i would much rather NOT do this myself for every deserialization...
> especially because in my desired usage, deserialized sequel model
> objects are buried inside other non-sequel model objects.
I assume you trust the JSON you are receiving?
My recommendation would be to use the existing json_serializer plugin
as the basis for your own custom plugin. Or just override the
json_create class method in your code, assuming you always want those
features:
class Ptime
def self.json_create(*)
obj = super
obj.instance_eval do
@new = false
@modified = false
changed_columns.clear
end
obj
end
end
With the patch I'll be committing, that hopefully will take care of
your needs.
Jeremy
--
You received this message because you are subscribed to the Google Groups
"sequel-talk" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to
[email protected].
For more options, visit this group at
http://groups.google.com/group/sequel-talk?hl=en.