jsog 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/jsog.rb +101 -0
  2. metadata +45 -0
@@ -0,0 +1,101 @@
1
+
2
+ require 'json'
3
+
4
+ class JSOG
5
+ class << self
6
+
7
+ # Convert a (Hash) object graph with potential cyclic references into a simpler structure
8
+ # which contains @id and @ref references.
9
+ #
10
+ # @param obj [Hash] the object graph to convert
11
+ # @return [Hash] an object graph with @ref instead of duplicate references
12
+ def encode(obj)
13
+ return do_encode(obj, {})
14
+ end
15
+
16
+ # Convert a (Hash) object graph that was encoded with encode() back to a normal structure
17
+ # with cyclic references.
18
+ #
19
+ # @param obj [Hash] an object graph that was created with encode()
20
+ # @return [Hash] an object graph with direct references instead of @ref
21
+ def decode(obj)
22
+ return do_decode(obj, {})
23
+ end
24
+
25
+ # Just like JSON.parse(), but reads JSOG. JSON is safe too.
26
+ def parse(str)
27
+ return decode(JSON.parse(str))
28
+ end
29
+
30
+ # Just like JSON.dump(), but outputs JSOG.
31
+ def dump(obj)
32
+ return JSON.dump(encode(obj))
33
+ end
34
+
35
+
36
+ private
37
+
38
+ def do_encode(original, sofar)
39
+ if original.is_a?(Array)
40
+ return encode_array(original, sofar)
41
+ elsif original.is_a?(Hash)
42
+ return encode_object(original, sofar)
43
+ else
44
+ return original
45
+ end
46
+ end
47
+
48
+ def encode_object(original, sofar)
49
+ original_id = original.object_id.to_s
50
+
51
+ if sofar.has_key?(original_id)
52
+ return { '@ref' => original_id }
53
+ end
54
+
55
+ result = sofar[original_id] = { '@id' => original_id }
56
+
57
+ original.each do |key, value|
58
+ result[key] = do_encode(value, sofar)
59
+ end
60
+
61
+ return result
62
+ end
63
+
64
+ def encode_array(original, sofar)
65
+ return original.map { |val| encode(val, sofar) }
66
+ end
67
+
68
+ #
69
+
70
+ def do_decode(encoded, found)
71
+ if encoded.is_a?(Array)
72
+ return decode_array(encoded, found)
73
+ elsif encoded.is_a?(Hash)
74
+ return decode_object(encoded, found)
75
+ else
76
+ return encoded
77
+ end
78
+ end
79
+
80
+ def decode_object(encoded, found)
81
+ ref = encoded['@ref']
82
+ return found[ref.to_s] if ref # be defensive if someone uses numbers in violation of the spec
83
+
84
+ result = {}
85
+
86
+ id = encoded['@id']
87
+ found[id.to_s] = result if id # be defensive if someone uses numbers in violation of the spec
88
+
89
+ encoded.each do |key, value|
90
+ result[key] = do_decode(value, found)
91
+ end
92
+
93
+ return result
94
+ end
95
+
96
+ def decode_array(encoded, found)
97
+ return encoded.map { |value| decode(value, found) }
98
+ end
99
+
100
+ end
101
+ end
metadata ADDED
@@ -0,0 +1,45 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: jsog
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Jeff Schnitzer
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-05-26 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Library to serialize and deserialize object graphs in the JSOG format
15
+ email: jeff@infohazard.org
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - lib/jsog.rb
21
+ homepage: https://github.com/stickfigure/jsog-ruby
22
+ licenses: []
23
+ post_install_message:
24
+ rdoc_options: []
25
+ require_paths:
26
+ - lib
27
+ required_ruby_version: !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ required_rubygems_version: !ruby/object:Gem::Requirement
34
+ none: false
35
+ requirements:
36
+ - - ! '>='
37
+ - !ruby/object:Gem::Version
38
+ version: '0'
39
+ requirements: []
40
+ rubyforge_project:
41
+ rubygems_version: 1.8.24
42
+ signing_key:
43
+ specification_version: 3
44
+ summary: JSOG serializer and deserializer
45
+ test_files: []