jinx-json 2.1.1 → 2.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/Gemfile CHANGED
@@ -4,6 +4,6 @@ gemspec
4
4
  group :development do
5
5
  gem 'ruby-debug'
6
6
  # Uncomment to use a local gem.
7
- gem 'jinx', :path => File.dirname(__FILE__) + '/../core'
7
+ #gem 'jinx', :path => File.dirname(__FILE__) + '/../core'
8
8
  gem 'jinx-json', :path => File.dirname(__FILE__), :require => 'jinx/json'
9
9
  end
data/History.md CHANGED
@@ -1,6 +1,10 @@
1
1
  This history lists major release themes. See the GitHub commits (https://github.com/jinx/json)
2
2
  for change details.
3
3
 
4
+ 2.1.2 / 2012-06-12
5
+ ------------------
6
+ * Support caSmall web service.
7
+
4
8
  2.1.1 / 2012-04-13
5
9
  ------------------
6
10
  * Initial public release spun off from caruby/core.
@@ -0,0 +1,32 @@
1
+ require 'date'
2
+ require 'java'
3
+
4
+ class DateTime
5
+ # @param [String] json the JSON to deserialize
6
+ # @return [Date] the deserialized object
7
+ def self.json_create(json)
8
+ parse(json['data'])
9
+ end
10
+
11
+ # Adds JSON serialization to Ruby Date.
12
+ #
13
+ # @param args the JSON serialization options
14
+ # @return [String] the serialized date
15
+ def to_json(*args)
16
+ {
17
+ 'json_class' => self.class.name,
18
+ 'data' => to_s
19
+ }.to_json(*args)
20
+ end
21
+ end
22
+
23
+ class Java::JavaUtil::Date
24
+ # Adds JSON serialization to Java Date.
25
+ # The JSON is deserialized as a Ruby Date.
26
+ #
27
+ # @param args the JSON serialization options
28
+ # @return [String] the serialized date
29
+ def to_json(*args)
30
+ to_ruby_date.to_json(*args)
31
+ end
32
+ end
@@ -0,0 +1,17 @@
1
+ require 'jinx/helpers/hashable'
2
+
3
+ module Jinx
4
+ module JSON
5
+ # This Deserializable mix-in adds a {Deserializer} to each class which extends this module.
6
+ module Deserializable
7
+ def included(other)
8
+ super
9
+ if Class === other then
10
+ other.extend(Deserializer)
11
+ else
12
+ other.extend(Deserializable)
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
@@ -1,16 +1,43 @@
1
1
  require 'jinx/helpers/hashable'
2
2
 
3
+ module JSON
4
+ # Bumps the default JSON nesting level to 100.
5
+ def self.parse(source, opts={})
6
+ visited = Thread.current[:jinx_json_deserialized] ||= {}
7
+ opts = opts.merge(:max_nesting => 100) unless opts.has_key?(:max_nesting)
8
+ begin
9
+ Parser.new(source, opts).parse
10
+ ensure
11
+ visited.clear
12
+ end
13
+ end
14
+ end
15
+
3
16
  module Jinx
4
17
  module JSON
5
18
  # JSON => {Jinx::Resource} deserializer.
6
19
  #
7
- # This Deserializer reconstitutes a jinxed object from a JSON string built by a {Serializer}.
20
+ # This Deserializer reconstitutes a jinxed object from a JSON string built
21
+ # by a {Serializable}.
8
22
  module Deserializer
9
23
  # @param [String] json the JSON to deserialize
10
24
  # @return [Jinx::Resource] the deserialized object
11
25
  def json_create(json)
12
- # Make the new object from the json data attribute => value hash.
13
- new(json['data'])
26
+ # the thread-local oid => object hash
27
+ visited = Thread.current[:jinx_json_deserialized]
28
+ # the payload
29
+ vh = json['data']
30
+ # the oid
31
+ oid = vh.delete('object_id')
32
+ # If the object has already been built, then return that object.
33
+ ref = visited[oid]
34
+ if ref then
35
+ # Fill in a place-holder with content.
36
+ ref.merge_attributes(vh) unless vh.empty?
37
+ return ref
38
+ end
39
+ # Make the new object from the attribute => value hash.
40
+ visited[oid] = new(vh)
14
41
  end
15
42
  end
16
43
  end
@@ -0,0 +1,88 @@
1
+ require 'json'
2
+ require 'jinx/json/state'
3
+ require 'jinx/json/collection'
4
+ require 'jinx/json/date'
5
+ require 'jinx/json/deserializable'
6
+ require 'jinx/json/deserializer'
7
+
8
+ module Jinx
9
+ module JSON
10
+ # Serializable is the JSON serializer {Jinx::Resource} mix-in.
11
+ #
12
+ # {#to_json} creates a JSON string from a jinxed object. The JSON payload is
13
+ # suitable for transfer to a remote {Deserializer}. This {Serializable} module
14
+ # is included directly in the jinxed application domain module after
15
+ # including {Jinx::Resource}, e.g.:
16
+ # module MyApp
17
+ # include Jinx::JSON::Serializable, Jinx:Resource
18
+ # which includes +Resource+ followed by the +Serializable+.
19
+ #
20
+ # The module which includes Serializable is extended with the {Importer}, which
21
+ # enables deserialization of the serialized JSON.
22
+ #
23
+ # The JSON payload is built as follows:
24
+ # * non-domain properties are serialized
25
+ # * dependent references are serialized recursively
26
+ # * independent reference primary and secondary key content is serialized
27
+ # * circular references are precluded by truncating the reference with a
28
+ # surrogate object id
29
+ module Serializable
30
+ def self.included(other)
31
+ super
32
+ if Class === other then
33
+ other.extend(Deserializer)
34
+ else
35
+ other.extend(Deserializable)
36
+ end
37
+ end
38
+
39
+ # @param [State, Hash, nil] state the JSON state or serialization options
40
+ # @return [String] the JSON representation of this {Jinx::Resource}
41
+ def to_json(state=nil)
42
+ # Make a new State from the options if this is a top-level call.
43
+ state = State.for(state) unless State === state
44
+ # the JSON content
45
+ {
46
+ 'json_class' => json_class_name,
47
+ 'data' => json_value_hash(state.visited)
48
+ }.to_json(state)
49
+ end
50
+
51
+ private
52
+
53
+ # The JSON class name must be scoped by the Resource package module, not the
54
+ # Java package, in order to recognize the Jinx::Resource JSON hooks.
55
+ #
56
+ # @return [String] the class name qualified by the Resource package module name context
57
+ def json_class_name
58
+ [self.class.domain_module, self.class.name.demodulize].join('::')
59
+ end
60
+
61
+ # Builds a serializable attribute => value hash with content as follows:
62
+ # * If this domain object has not yet been visited, then the hash includes all attributes,
63
+ # as well as the +Jinx::Resource#proxy_object_id+.
64
+ # * If this domain object has already been visited, then the hash includes only the
65
+ # +proxy_object_id+.
66
+ # Each +Set+ attribute value is converted to an array, since JSON does not serialize
67
+ # a +Set+ properly.
68
+ #
69
+ # The {Deserializer} is responsible for reconstituting the domain object graph from the
70
+ # serialized content.
71
+ #
72
+ # @param [<Resource>] visited the serialized objects
73
+ # @return [{Symbol => Object}] the serializable value hash
74
+ def json_value_hash(visited)
75
+ # If already visited, then the only content is the object id.
76
+ if visited.include?(self) then
77
+ return {:object_id => proxy_object_id}
78
+ end
79
+ visited << self
80
+ vh = value_hash
81
+ vh.each { |pa, v| vh[pa] = v.to_a if Set === v }
82
+ # Add the object id.
83
+ vh[:object_id] = proxy_object_id
84
+ vh
85
+ end
86
+ end
87
+ end
88
+ end
File without changes
@@ -0,0 +1,24 @@
1
+ require 'set'
2
+
3
+ module Jinx
4
+ module JSON
5
+ # This State module bumps the JSON default +:max_nesting+ to 100 and tracks
6
+ # the visited objects in a modified +JSON::Pure::Generator::State+.
7
+ module State
8
+ # @param [Hash, nil] opts the generator options
9
+ # return [State] the state for the given options
10
+ def self.for(opts)
11
+ opts ||= {}
12
+ opts[:max_nesting] ||= 100
13
+ state = ::JSON::Pure::Generator::State.from_state(opts)
14
+ class << state
15
+ # @return [<Jinx::JSON::Serializable>] the serialized objects
16
+ def visited
17
+ @visited ||= Set.new
18
+ end
19
+ end
20
+ state
21
+ end
22
+ end
23
+ end
24
+ end
@@ -1,5 +1,5 @@
1
1
  module Jinx
2
2
  module JSON
3
- VERSION = "2.1.1"
3
+ VERSION = '2.1.2'
4
4
  end
5
5
  end
@@ -2,28 +2,28 @@ require 'spec/spec_helper'
2
2
 
3
3
  module Family
4
4
  describe Address do
5
- it "should serialize an address" do
6
- a = Address.new(:street1 => '16 Elm St', :city => 'Peoria', :state => 'IL')
7
- j = JSON[a.to_json]
8
- j.street1.should == a.street1
9
- j.city.should == a.city
10
- j.state.should == a.state
5
+ it 'should serialize an address' do
6
+ addr = Address.new(:street1 => '16 Elm St', :city => 'Peoria', :state => 'IL')
7
+ j = JSON[addr.to_json]
8
+ j.street1.should == addr.street1
9
+ j.city.should == addr.city
10
+ j.state.should == addr.state
11
11
  end
12
12
  end
13
13
 
14
14
  describe Household do
15
- it "should serialize the address" do
16
- a = Address.new(:street1 => '16 Elm St', :city => 'Peoria', :state => 'IL')
17
- h = Household.new(:address => a)
18
- j = JSON[h.to_json]
19
- j.address.street1.should == a.street1
20
- j.address.city.should == a.city
21
- j.address.state.should == a.state
15
+ it 'should serialize the address' do
16
+ addr = Address.new(:street1 => '16 Elm St', :city => 'Peoria', :state => 'IL')
17
+ hshd = Household.new(:address => addr)
18
+ j = JSON[hshd.to_json]
19
+ j.address.street1.should == addr.street1
20
+ j.address.city.should == addr.city
21
+ j.address.state.should == addr.state
22
22
  end
23
23
  end
24
24
 
25
25
  describe Parent do
26
- it "should serialize the children" do
26
+ it 'should serialize the children' do
27
27
  p = Parent.new(:name => 'Oscar')
28
28
  c = Child.new(:name => 'Beauregard', :parents => [p])
29
29
  p.children << c
@@ -33,14 +33,22 @@ module Family
33
33
  end
34
34
 
35
35
  describe Child do
36
- it "should only serialize the owner key" do
37
- h = Household.new
38
- p = Parent.new(:name => 'Oscar', :household => h)
36
+ it 'should serialize the parent' do
37
+ hshd = Household.new
38
+ p = Parent.new(:name => 'Oscar', :household => hshd)
39
39
  c = Child.new(:name => 'Beauregard', :parents => [p])
40
40
  p.children << c
41
41
  j = JSON[c.to_json]
42
- j.parents.first.name.should be nil
43
- j.parents.first.household.should be nil
42
+ j.parents.first.name.should_not be nil
43
+ j.parents.first.household.should_not be nil
44
+ end
45
+
46
+ describe 'Date' do
47
+ it 'should serialize a Java date as a Ruby date' do
48
+ date = Java.now
49
+ j = JSON[date.to_json]
50
+ j.should be_within(0.005).of(date.to_ruby_date)
51
+ end
44
52
  end
45
53
  end
46
54
  end
data/spec/spec_helper.rb CHANGED
@@ -6,8 +6,8 @@ Bundler.require(:test, :development)
6
6
  require Bundler.environment.specs.detect { |s| s.name == 'jinx' }.full_gem_path + '/examples/family/lib/family'
7
7
 
8
8
  # Add serialization
9
- require 'jinx/json/serializer'
9
+ require 'jinx/json/serializable'
10
10
 
11
11
  module Family
12
- include Jinx::JSON::Serializer
12
+ include Jinx::JSON::Serializable
13
13
  end
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: jinx-json
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 2.1.1
5
+ version: 2.1.2
6
6
  platform: ruby
7
7
  authors:
8
8
  - OHSU
@@ -10,8 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2012-04-13 00:00:00 -07:00
14
- default_executable:
13
+ date: 2012-06-12 00:00:00 Z
15
14
  dependencies:
16
15
  - !ruby/object:Gem::Dependency
17
16
  name: bundler
@@ -81,21 +80,22 @@ files:
81
80
  - .rspec
82
81
  - .yardopts
83
82
  - Gemfile
84
- - Gemfile.lock
85
83
  - History.md
86
84
  - LEGAL
87
85
  - LICENSE
88
86
  - README.md
89
87
  - Rakefile
90
88
  - jinx-json.gemspec
91
- - lib/jinx/json.rb
92
89
  - lib/jinx/json/collection.rb
90
+ - lib/jinx/json/date.rb
91
+ - lib/jinx/json/deserializable.rb
93
92
  - lib/jinx/json/deserializer.rb
94
- - lib/jinx/json/serializer.rb
93
+ - lib/jinx/json/serializable.rb
94
+ - lib/jinx/json/set.rb
95
+ - lib/jinx/json/state.rb
95
96
  - lib/jinx/json/version.rb
96
97
  - spec/serializer_spec.rb
97
98
  - spec/spec_helper.rb
98
- has_rdoc: yard
99
99
  homepage: http://github.com/jinx/json
100
100
  licenses:
101
101
  - MIT
@@ -119,10 +119,11 @@ required_rubygems_version: !ruby/object:Gem::Requirement
119
119
  requirements: []
120
120
 
121
121
  rubyforge_project: jinx
122
- rubygems_version: 1.5.1
122
+ rubygems_version: 1.8.15
123
123
  signing_key:
124
124
  specification_version: 3
125
125
  summary: Jinx JSON plug-in.
126
126
  test_files:
127
127
  - spec/serializer_spec.rb
128
128
  - spec/spec_helper.rb
129
+ has_rdoc: yard
data/Gemfile.lock DELETED
@@ -1,43 +0,0 @@
1
- PATH
2
- remote: .
3
- specs:
4
- jinx-json (2.1.1)
5
- bundler
6
- jinx
7
- json_pure
8
-
9
- PATH
10
- remote: /Users/loneyf/workspace/jinx/core
11
- specs:
12
- jinx (2.1.1)
13
- bundler
14
-
15
- GEM
16
- remote: http://rubygems.org/
17
- specs:
18
- columnize (0.3.6)
19
- diff-lcs (1.1.3)
20
- json_pure (1.6.3)
21
- rake (0.9.2.2)
22
- rspec (2.9.0)
23
- rspec-core (~> 2.9.0)
24
- rspec-expectations (~> 2.9.0)
25
- rspec-mocks (~> 2.9.0)
26
- rspec-core (2.9.0)
27
- rspec-expectations (2.9.1)
28
- diff-lcs (~> 1.1.3)
29
- rspec-mocks (2.9.0)
30
- ruby-debug (0.10.4)
31
- columnize (>= 0.1)
32
- ruby-debug-base (~> 0.10.4.0)
33
- ruby-debug-base (0.10.4-java)
34
-
35
- PLATFORMS
36
- java
37
-
38
- DEPENDENCIES
39
- jinx!
40
- jinx-json!
41
- rake
42
- rspec (>= 2.6)
43
- ruby-debug
@@ -1,90 +0,0 @@
1
- require 'json'
2
- require 'jinx/json/collection'
3
-
4
- module Jinx
5
- module JSON
6
- # {Jinx::Resource} => JSON serializer.
7
- #
8
- # This Serializer creates a JSON string from a jinxed object. The JSON payload is
9
- # suitable for transfer to a remote {Deserializer}. This {Serializer} is included
10
- # directly in the jinxed application domain module after including {Jinx::Resource},
11
- # e.g.:
12
- # module MyApp
13
- # include Jinx::JSON::Serializer, Jinx:Resource
14
- # which includes +Resource+ followed by the +Serializer+.
15
- #
16
- # The module which includes this Serializer is extended with the {Importer}, which
17
- # enables deserialization of the serialized JSON.
18
- #
19
- # The JSON payload is built as follows:
20
- # * non-domain properties are serialized
21
- # * dependent references are serialized recursively
22
- # * independent reference primary and secondary key content is serialized
23
- module Serializer
24
- # @param args the JSON serialization options
25
- # @return [String] the JSON representation of this {Jinx::Resource}
26
- def to_json(*args)
27
- {
28
- 'json_class' => json_class_name,
29
- 'data' => json_value_hash
30
- }.to_json(*args)
31
- end
32
-
33
- private
34
-
35
- # The JSON class name must be scoped by the Resource package module, not the
36
- # Java package, in order to recognize the Jinx::Resource JSON hooks.
37
- #
38
- # @return [String] the class name qualified by the Resource package module name context
39
- def json_class_name
40
- [self.class.domain_module, self.class.name.demodulize].join('::')
41
- end
42
-
43
- # Builds a serializable attribute => value hash. If _key_only _ is true, then only
44
- # the key attributes are included in the hash. Otherwise, all properties are included
45
- # in the hash.
46
- #
47
- # An independent or owner attribute value is a copy of the referenced domain object
48
- # consisting of only the primary and secondary key attributes.
49
- #
50
- # @return [{Symbol => Object}] the serializable value hash
51
- def json_value_hash
52
- vh = value_hash(self.class.nondomain_attributes)
53
- vh.merge!(value_hash(self.class.dependent_attributes))
54
- self.class.independent_attributes.each do |ia|
55
- ref = send(ia)
56
- vh[ia] = json_independent_reference(ref) unless ref.nil_or_empty?
57
- end
58
- vh
59
- end
60
-
61
- # @param [Resource] the referenced object
62
- # @return [Resource] a copy of the referenced object which only contains
63
- # key property values
64
- def json_independent_reference(ref)
65
- return ref.map { |item| json_independent_reference(item) } if ref.collection?
66
- vh = json_key_hash(ref)
67
- ref.copy(vh) unless vh.empty?
68
- end
69
-
70
- # @param (see #json_independent_reference)
71
- # @return [{Symbol => Object}, nil] the key attribute => value hash, or nil
72
- # if there is no complete key
73
- def json_key_hash(ref)
74
- vh = ref.value_hash(ref.class.primary_key_attributes)
75
- ref.class.secondary_key_attributes.each do |ka|
76
- value = json_key_value(ref, ka)
77
- vh[ka] = value if value
78
- end
79
- end
80
-
81
- # @param (see #json_independent_reference)
82
- # @param [Symbol] the key value
83
- # @return the key attribute value
84
- def json_key_value(ref, attribute)
85
- value = ref.send(attribute)
86
- Resource === value ? json_independent_reference(value) : value
87
- end
88
- end
89
- end
90
- end
data/lib/jinx/json.rb DELETED
@@ -1 +0,0 @@
1
- require 'json'