Skip to content

Commit

Permalink
Support include_classes option on dump / include_classes.rb sample …
Browse files Browse the repository at this point in the history
…/ cycle.rb sample
  • Loading branch information
AndyObtiva committed Dec 27, 2020
1 parent 83b443f commit 3b0dc2b
Show file tree
Hide file tree
Showing 9 changed files with 519 additions and 13 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
- Serialize struct member values as JSON
- Serialize classes/modules as JSON
- Serialize cycles by using object ID references
- Support `include_classes` option on dump
- Deserialize instance variables as JSON
- Deserialize Class occurence in variables as JSON
- Deserialize Module occurence in variables as JSON
135 changes: 134 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ require 'yasl'

To serialize, use the `YASL#dump` method.

Example (from [samples/sample.rb](samples/sample.rb)):
Example (from [samples/basic.rb](samples/basic.rb)):

```ruby
require 'yasl'
Expand Down Expand Up @@ -76,6 +76,139 @@ puts dump.inspect
# => "{\"_class\":\"Car\",\"_id\":1,\"_instance_variables\":{\"make\":\"Mitsubishi\",\"model\":\"Eclipse\",\"year\":\"2002\",\"registration_time\":{\"_class\":\"Time\",\"_data\":[0,2452932,49177,\"12644383719423828125/137438953472\",-10800,2299161.0]},\"registration_date\":{\"_class\":\"Date\",\"_data\":[0,2452932,0,0,0,2299161.0]},\"registration_date_time\":{\"_class\":\"DateTime\",\"_data\":[0,2452932,49177,92000000,-10800,2299161.0]},\"complex_number\":{\"_class\":\"Complex\",\"_data\":\"2+37i\"},\"complex_polar_number\":{\"_class\":\"Complex\",\"_data\":\"22.13993492521203-6.230833131080988i\"},\"rational_number\":{\"_class\":\"Rational\",\"_data\":\"3/1\"}}}"
```

#### Cycles

YASL automatically detects cycles when serializing bidirectional object references.

Example (from [samples/cycle.rb](samples/cycle.rb)):

```ruby
$LOAD_PATH.unshift File.expand_path(File.join(__dir__, '..', 'lib'))

require 'yasl'

class Car
attr_accessor :make,
:model,
:year,
:owner
end

class Person
class << self
def reset_count!
@count = 0
end

def increment_count!
@count ||= 0
@count += 1
end

def reset_class_count!
@@class_count = 0
end

def increment_class_count!
@@class_count = 0 unless defined?(@@class_count)
@@class_count += 1
end
end

attr_accessor :name, :dob, :cars

def initialize
self.class.increment_count!
self.class.increment_class_count!
end
end

person = Person.new
person.name = 'Sean Hux'
person.dob = Time.new(2017, 10, 17, 10, 3, 4)

car = Car.new
car.make = 'Mitsubishi'
car.model = 'Eclipse'
car.year = '2002'

car.owner = person
person.cars = [car]

dump = YASL.dump(car)

puts dump.inspect

# => "{\"_class\":\"Car\",\"_id\":1,\"_instance_variables\":{\"make\":\"Mitsubishi\",\"model\":\"Eclipse\",\"owner\":{\"_class\":\"Person\",\"_id\":1,\"_instance_variables\":{\"cars\":{\"_class\":\"Array\",\"_data\":[{\"_class\":\"Car\",\"_id\":1}]},\"dob\":{\"_class\":\"Time\",\"_data\":[0,2458044,50584,0,-14400,2299161.0]},\"name\":\"Sean Hux\"}},\"year\":\"2002\"}}"
```

#### `include_classes` option

(default: `false`)

Passing `include_classes: true` to the `YASL#dump` method causes YASL to serialize classes and modules too (class variables and singleton class instance variables). They go under the `_classes` array.

Example (from [samples/include_classes.rb](samples/include_classes.rb)):

```ruby
$LOAD_PATH.unshift File.expand_path(File.join(__dir__, '..', 'lib'))

require 'yasl'

class Car
attr_accessor :make,
:model,
:year,
:owner
end

class Person
class << self
def reset_count!
@count = 0
end

def increment_count!
@count ||= 0
@count += 1
end

def reset_class_count!
@@class_count = 0
end

def increment_class_count!
@@class_count = 0 unless defined?(@@class_count)
@@class_count += 1
end
end

attr_accessor :name, :dob

def initialize
self.class.increment_count!
self.class.increment_class_count!
end
end

person = Person.new
person.name = 'Sean Hux'
person.dob = Time.new(2017, 10, 17, 10, 3, 4)

car = Car.new
car.make = 'Mitsubishi'
car.model = 'Eclipse'
car.year = '2002'
car.owner = person

dump = YASL.dump(car, include_classes: true)

puts dump.inspect

# => "{\"_class\":\"Car\",\"_id\":1,\"_instance_variables\":{\"make\":\"Mitsubishi\",\"model\":\"Eclipse\",\"owner\":{\"_class\":\"Person\",\"_id\":1,\"_instance_variables\":{\"dob\":{\"_class\":\"Time\",\"_data\":[0,2458044,50584,0,-14400,2299161.0]},\"name\":\"Sean Hux\"}},\"year\":\"2002\"},\"_classes\":[{\"_class\":\"Person\",\"_class_variables\":{\"class_count\":1},\"_instance_variables\":{\"count\":1}}]}"
```


### Deserialize

[DESERIALIZE NOT FULLY IMPLEMENTED]
Expand Down
3 changes: 2 additions & 1 deletion TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@
- Deserialize top-level Class occurence in variables as JSON
- Deserialize top-level Module occurence in variables as JSON
- Deal with bypassing constructor args (perhaps providing an alternative to new)
- Serialize whether a class reference is a class or module
- Materialize a class matching the non-existing class
- Support `include_classes` option on both dump and load
- Support `include_classes` option on load
- Support passing `whitelist_classes` to filter by upon load

## Soon
Expand Down
2 changes: 1 addition & 1 deletion lib/yasl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ module YASL
RESERVED_KEYS = []

class << self
def dump(object, include_classes: true)
def dump(object, include_classes: false)
JSON.dump(Dumper.new(object).dump(include_classes: include_classes))
end

Expand Down
2 changes: 1 addition & 1 deletion lib/yasl/dumper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ def initialize(object)
@class_objects = {}
end

def dump(include_classes: true)
def dump(include_classes: false)
structure = dump_structure(object)
structure.merge!(dump_classes_structure(object)) if include_classes && structure.is_a?(Hash)
structure
Expand Down
File renamed without changes.
55 changes: 55 additions & 0 deletions samples/cycle.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
$LOAD_PATH.unshift File.expand_path(File.join(__dir__, '..', 'lib'))

require 'yasl'

class Car
attr_accessor :make,
:model,
:year,
:owner
end

class Person
class << self
def reset_count!
@count = 0
end

def increment_count!
@count ||= 0
@count += 1
end

def reset_class_count!
@@class_count = 0
end

def increment_class_count!
@@class_count = 0 unless defined?(@@class_count)
@@class_count += 1
end
end

attr_accessor :name, :dob, :cars

def initialize
self.class.increment_count!
self.class.increment_class_count!
end
end

person = Person.new
person.name = 'Sean Hux'
person.dob = Time.new(2017, 10, 17, 10, 3, 4)

car = Car.new
car.make = 'Mitsubishi'
car.model = 'Eclipse'
car.year = '2002'

car.owner = person
person.cars = [car]

dump = YASL.dump(car)

puts dump.inspect
53 changes: 53 additions & 0 deletions samples/include_classes.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
$LOAD_PATH.unshift File.expand_path(File.join(__dir__, '..', 'lib'))

require 'yasl'

class Car
attr_accessor :make,
:model,
:year,
:owner
end

class Person
class << self
def reset_count!
@count = 0
end

def increment_count!
@count ||= 0
@count += 1
end

def reset_class_count!
@@class_count = 0
end

def increment_class_count!
@@class_count = 0 unless defined?(@@class_count)
@@class_count += 1
end
end

attr_accessor :name, :dob

def initialize
self.class.increment_count!
self.class.increment_class_count!
end
end

person = Person.new
person.name = 'Sean Hux'
person.dob = Time.new(2017, 10, 17, 10, 3, 4)

car = Car.new
car.make = 'Mitsubishi'
car.model = 'Eclipse'
car.year = '2002'
car.owner = person

dump = YASL.dump(car, include_classes: true)

puts dump.inspect
Loading

0 comments on commit 3b0dc2b

Please sign in to comment.