Skip to content

Commit

Permalink
Deserialize class variables as JSON / Support include_classes optio…
Browse files Browse the repository at this point in the history
…n on load
  • Loading branch information
AndyObtiva committed Dec 28, 2020
1 parent ae786dd commit 53a144d
Show file tree
Hide file tree
Showing 6 changed files with 45 additions and 22 deletions.
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,5 @@
- Deserialize instance variables as JSON
- Deserialize Class occurence in variables as JSON
- Deserialize Module occurence in variables as JSON
- Deserialize class variables as JSON
- Support `include_classes` option on load
4 changes: 1 addition & 3 deletions TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
## Next

- Deserialize Struct members as JSON
- Deserialize class variables as JSON
- Deserialize classes and modules
- Support `include_classes` option on load
- Deserialize top-level classes and modules
- 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)
Expand Down
4 changes: 2 additions & 2 deletions lib/yasl.rb
Original file line number Diff line number Diff line change
Expand Up @@ -37,8 +37,8 @@ def dump(object, include_classes: false)
JSON.dump(Dumper.new(object).dump(include_classes: include_classes))
end

def load(data)
Loader.new(JSON.load(data)).load
def load(data, include_classes: false)
Loader.new(JSON.load(data)).load(include_classes: include_classes)
end

def json_basic_data_type?(object)
Expand Down
12 changes: 6 additions & 6 deletions lib/yasl/dumper.rb
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def initialize(object)

def dump(include_classes: false)
structure = dump_structure(object)
structure.merge!(dump_classes_structure(object)) if include_classes && structure.is_a?(Hash)
structure.merge!(dump_classes_structure) if include_classes && structure.is_a?(Hash)
structure
end

Expand All @@ -51,7 +51,7 @@ def dump_structure(object, for_classes: false)
structure
end

def dump_classes_structure(object)
def dump_classes_structure
structure = {}
structure[:_classes] ||= []
@original_classes = []
Expand Down Expand Up @@ -93,11 +93,11 @@ def dump_non_basic_data_type_structure(object)
klass = class_for(object)
add_to_classes(klass)
structure[:_class] = klass.name
the_object_id = object_id(object)
if the_object_id.nil?
the_class_object_id = class_object_id(object)
if the_class_object_id.nil?
structure.merge!(dump_new_non_basic_data_type_structure(object))
else
structure[:_id] = the_object_id
structure[:_id] = the_class_object_id
end
structure
end
Expand Down Expand Up @@ -159,7 +159,7 @@ def add_to_classes(object)
classes << object unless classes.include?(object)
end

def object_id(object)
def class_object_id(object)
object_class_array = class_objects[class_for(object)]
object_class_array_index = object_class_array&.index(object)
(object_class_array_index + 1) unless object_class_array_index.nil?
Expand Down
26 changes: 20 additions & 6 deletions lib/yasl/loader.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,16 @@ def initialize(structure)
@class_objects = {}
end

def load
load_structure(structure)
def load(include_classes: false)
load_structure(structure).tap do
load_classes_structure if include_classes
end
end

def load_classes_structure
structure['_classes'].each do |class_structure|
load_non_basic_data_type_object(class_structure, for_classes: true)
end
end

def load_structure(structure, for_classes: false)
Expand All @@ -45,17 +53,23 @@ def load_structure(structure, for_classes: false)

private

def load_non_basic_data_type_object(structure)
def load_non_basic_data_type_object(structure, for_classes: false)
class_name = structure['_class']
klass = class_for(class_name)
add_to_classes(klass)
klass.alias_method(:initialize_without_yasl, :initialize)
object = klass.new
add_to_class_array(object)
structure['_instance_variables'].each do |instance_var, value|
object = for_classes ? klass : klass.new
add_to_class_array(object) unless for_classes
structure['_instance_variables'].to_a.each do |instance_var, value|
value = load_structure(value)
object.instance_variable_set("@#{instance_var}".to_sym, value)
end
if for_classes
structure['_class_variables'].to_a.each do |class_var, value|
value = load_structure(value)
object.class_variable_set("@@#{class_var}".to_sym, value)
end
end
object
ensure
klass.define_method(:initialize, klass.instance_method(:initialize_without_yasl))
Expand Down
19 changes: 14 additions & 5 deletions spec/lib/yasl_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ def increment_class_count!
end

def class_count
@class_count
@@class_count
end
end

Expand Down Expand Up @@ -1129,8 +1129,10 @@ def initialize
context 'Ruby objects and basic data types' do
it 'serializes instance variables of all Ruby basic data types' do
car1
car2
car3

object = YASL.load(JSON.dump(
data = JSON.dump(
_class: car1.class.name,
_id: 1,
_instance_variables: {
Expand Down Expand Up @@ -1206,11 +1208,18 @@ def initialize
},
},
],
))
)
object = YASL.load(data)

expect(object).to eq(car1)
expect(Car.count).to_not eq(1)
expect(Car.class_count).to_not eq(1)

object = YASL.load(data, include_classes: true)

expect(object).to eq(car1)
# expect(Car.count).to eq(1)
# expect(Car.class_count).to eq(1)
expect(Car.count).to eq(1)
expect(Car.class_count).to eq(1)
end
end

Expand Down

0 comments on commit 53a144d

Please sign in to comment.