pigeon_hole 0.0.1
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.
- checksums.yaml +7 -0
- data/lib/pigeon_hole/json_date.rb +29 -0
- data/lib/pigeon_hole/json_date_time.rb +41 -0
- data/lib/pigeon_hole/json_symbol.rb +22 -0
- data/lib/pigeon_hole/json_time.rb +34 -0
- data/lib/pigeon_hole/typed_json.rb +40 -0
- data/lib/pigeon_hole.rb +19 -0
- data/spec/integration_spec.rb +99 -0
- data/spec/spec_helper.rb +33 -0
- metadata +54 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 9f679f4b70108c6d3d567f1905462749de53dd26
|
4
|
+
data.tar.gz: c98c767931a8f0e1799e7db0d743c484ac46abf7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 7fa933c8432ae976cc51a96f9ca01355d9ccdece601844411207752f629cb5a31fc89337827c91944426dd5b2e971d1351e44131185f09bc046eeedc00ca9e49
|
7
|
+
data.tar.gz: d3384729d4a8a7bdd0cf82a6099fea598fdfb62da7fea3e66dc7a4e0242c203b43e9db9539aaf721c101bebd4124a2088acc14f66d9efe8cf4d7f8969d2149f6
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module PigeonHole
|
2
|
+
class JSONDate < SimpleDelegator
|
3
|
+
# Deserializes JSON string by converting Julian year <tt>y</tt>, month
|
4
|
+
# <tt>m</tt>, day <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> to Date.
|
5
|
+
def self.json_create(object)
|
6
|
+
Date.civil(*object.values_at('y', 'm', 'd', 'sg'))
|
7
|
+
end
|
8
|
+
|
9
|
+
#alias start sg unless method_defined?(:start)
|
10
|
+
|
11
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
12
|
+
# object.
|
13
|
+
def as_json(*)
|
14
|
+
{
|
15
|
+
JSON.create_id => self.class.name,
|
16
|
+
'y' => year,
|
17
|
+
'm' => month,
|
18
|
+
'd' => day,
|
19
|
+
'sg' => start,
|
20
|
+
}
|
21
|
+
end
|
22
|
+
|
23
|
+
# Stores class name (Date) with Julian year <tt>y</tt>, month <tt>m</tt>, day
|
24
|
+
# <tt>d</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
|
25
|
+
def to_json(*args)
|
26
|
+
as_json.to_json(*args)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module PigeonHole
|
2
|
+
class JSONDateTime < SimpleDelegator
|
3
|
+
# Deserializes JSON string by converting year <tt>y</tt>, month <tt>m</tt>,
|
4
|
+
# day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
|
5
|
+
# offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> to DateTime.
|
6
|
+
def self.json_create(object)
|
7
|
+
args = object.values_at('y', 'm', 'd', 'H', 'M', 'S')
|
8
|
+
of_a, of_b = object['of'].split('/')
|
9
|
+
if of_b and of_b != '0'
|
10
|
+
args << DateTime.send(:Rational, of_a.to_i, of_b.to_i)
|
11
|
+
else
|
12
|
+
args << of_a
|
13
|
+
end
|
14
|
+
args << object['sg']
|
15
|
+
DateTime.civil(*args)
|
16
|
+
end
|
17
|
+
|
18
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
19
|
+
# object.
|
20
|
+
def as_json(*)
|
21
|
+
{
|
22
|
+
JSON.create_id => self.class.name,
|
23
|
+
'y' => year,
|
24
|
+
'm' => month,
|
25
|
+
'd' => day,
|
26
|
+
'H' => hour,
|
27
|
+
'M' => min,
|
28
|
+
'S' => sec,
|
29
|
+
'of' => offset.to_s,
|
30
|
+
'sg' => start,
|
31
|
+
}
|
32
|
+
end
|
33
|
+
|
34
|
+
# Stores class name (DateTime) with Julian year <tt>y</tt>, month <tt>m</tt>,
|
35
|
+
# day <tt>d</tt>, hour <tt>H</tt>, minute <tt>M</tt>, second <tt>S</tt>,
|
36
|
+
# offset <tt>of</tt> and Day of Calendar Reform <tt>sg</tt> as JSON string
|
37
|
+
def to_json(*args)
|
38
|
+
as_json.to_json(*args)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module PigeonHole
|
2
|
+
class JSONSymbol < SimpleDelegator
|
3
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
4
|
+
# object.
|
5
|
+
def as_json(*)
|
6
|
+
{
|
7
|
+
JSON.create_id => self.class.name,
|
8
|
+
's' => to_s,
|
9
|
+
}
|
10
|
+
end
|
11
|
+
|
12
|
+
# Stores class name (Symbol) with String representation of Symbol as a JSON string.
|
13
|
+
def to_json(*a)
|
14
|
+
as_json.to_json(*a)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Deserializes JSON string by converting the <tt>string</tt> value stored in the object to a Symbol
|
18
|
+
def self.json_create(o)
|
19
|
+
o['s'].to_sym
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
module PigeonHole
|
2
|
+
class JSONTime < SimpleDelegator
|
3
|
+
# Deserializes JSON string by converting time since epoch to Time
|
4
|
+
def self.json_create(object)
|
5
|
+
if usec = object.delete('u') # used to be tv_usec -> tv_nsec
|
6
|
+
object['n'] = usec * 1000
|
7
|
+
end
|
8
|
+
if method_defined?(:tv_nsec)
|
9
|
+
Time.at(object['s'], Time.Rational(object['n'], 1000))
|
10
|
+
else
|
11
|
+
Time.at(object['s'], object['n'] / 1000)
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
# Returns a hash, that will be turned into a JSON object and represent this
|
16
|
+
# object.
|
17
|
+
def as_json(*)
|
18
|
+
nanoseconds = [ tv_usec * 1000 ]
|
19
|
+
respond_to?(:tv_nsec) and nanoseconds << tv_nsec
|
20
|
+
nanoseconds = nanoseconds.max
|
21
|
+
{
|
22
|
+
JSON.create_id => self.class.name,
|
23
|
+
's' => tv_sec,
|
24
|
+
'n' => nanoseconds,
|
25
|
+
}
|
26
|
+
end
|
27
|
+
|
28
|
+
# Stores class name (Time) with number of seconds since epoch and number of
|
29
|
+
# microseconds for Time as JSON string
|
30
|
+
def to_json(*args)
|
31
|
+
as_json.to_json(*args)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'json'
|
2
|
+
|
3
|
+
module PigeonHole
|
4
|
+
class TypedJSON
|
5
|
+
def self.generate(obj, *args)
|
6
|
+
hash_dup = each_with_parent(obj)
|
7
|
+
JSON.generate(hash_dup, *args)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.map_to_json(obj)
|
11
|
+
case obj
|
12
|
+
when Time
|
13
|
+
JSONTime.new(obj)
|
14
|
+
when DateTime
|
15
|
+
JSONDateTime.new(obj)
|
16
|
+
when Date
|
17
|
+
JSONDate.new(obj)
|
18
|
+
when Symbol
|
19
|
+
JSONSymbol.new(obj)
|
20
|
+
else
|
21
|
+
obj
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.each_with_parent(hash, result=nil)
|
26
|
+
duplicated_hash = {} || result
|
27
|
+
|
28
|
+
hash.each do |k, v|
|
29
|
+
case v
|
30
|
+
when Hash
|
31
|
+
duplicated_hash[k] = each_with_parent(v, duplicated_hash)
|
32
|
+
else
|
33
|
+
duplicated_hash[k] = map_to_json(v)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
duplicated_hash
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
data/lib/pigeon_hole.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
module PigeonHole
|
2
|
+
require_relative 'pigeon_hole/typed_json'
|
3
|
+
require_relative 'pigeon_hole/json_date'
|
4
|
+
require_relative 'pigeon_hole/json_date_time'
|
5
|
+
require_relative 'pigeon_hole/json_symbol'
|
6
|
+
require_relative 'pigeon_hole/json_time'
|
7
|
+
|
8
|
+
def self.generate(obj, *args)
|
9
|
+
TypedJSON.generate(obj, *args)
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.parse(string)
|
13
|
+
load(string)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.load(string)
|
17
|
+
JSON.load(string)
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "serializing dates" do
|
4
|
+
let(:date) { random_date }
|
5
|
+
|
6
|
+
subject { PigeonHole.generate(date: date) }
|
7
|
+
|
8
|
+
it "serializes hash into a string" do
|
9
|
+
result = subject
|
10
|
+
expect(result).to_not be_empty
|
11
|
+
end
|
12
|
+
|
13
|
+
it "can be deserialized to a date time" do
|
14
|
+
result = subject
|
15
|
+
hash = PigeonHole.parse(result)
|
16
|
+
expect(hash).to eq({ "date" => date })
|
17
|
+
expect(hash["date"]).to be_a(Date)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "serializing times" do
|
22
|
+
let(:time) { random_time }
|
23
|
+
|
24
|
+
subject { PigeonHole.generate(time: time) }
|
25
|
+
|
26
|
+
it "serializes hash into a string" do
|
27
|
+
result = subject
|
28
|
+
expect(result).to_not be_empty
|
29
|
+
end
|
30
|
+
|
31
|
+
it "can be deserialized to a time" do
|
32
|
+
result = subject
|
33
|
+
hash = PigeonHole.parse(result)
|
34
|
+
expect(hash).to eq({ "time" => time })
|
35
|
+
expect(hash["time"]).to be_a(Time)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
describe "serializing datetimes" do
|
40
|
+
let(:date_time) { random_date_time }
|
41
|
+
|
42
|
+
subject { PigeonHole.generate(date_time: date_time) }
|
43
|
+
|
44
|
+
it "serializes hash into a string" do
|
45
|
+
result = subject
|
46
|
+
expect(result).to_not be_empty
|
47
|
+
end
|
48
|
+
|
49
|
+
it "can be deserialized to a date_time" do
|
50
|
+
result = subject
|
51
|
+
hash = PigeonHole.parse(result)
|
52
|
+
expect(hash["date_time"]).to be_a(DateTime)
|
53
|
+
expect(hash["date_time"].to_date).to eq(date_time.to_date)
|
54
|
+
expect(hash["date_time"].to_time.to_i).to eq(date_time.to_time.to_i)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
describe "serializing symbols" do
|
59
|
+
let(:symbol) { :a_symbol }
|
60
|
+
|
61
|
+
subject { PigeonHole.generate(symbol: symbol) }
|
62
|
+
|
63
|
+
it "serializes hash into a string" do
|
64
|
+
result = subject
|
65
|
+
expect(result).to_not be_empty
|
66
|
+
end
|
67
|
+
|
68
|
+
it "can be deserialized to a symbol" do
|
69
|
+
result = subject
|
70
|
+
hash = PigeonHole.parse(result)
|
71
|
+
expect(hash).to eq({ "symbol" => symbol })
|
72
|
+
expect(hash["symbol"]).to be_a(Symbol)
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
describe "serializing nested hashes" do
|
77
|
+
let(:expected) do
|
78
|
+
{
|
79
|
+
foo: {
|
80
|
+
bar: random_time,
|
81
|
+
baz: :temp
|
82
|
+
}
|
83
|
+
}
|
84
|
+
end
|
85
|
+
|
86
|
+
subject { PigeonHole.generate(expected) }
|
87
|
+
|
88
|
+
it "serializes hash into a string" do
|
89
|
+
result = subject
|
90
|
+
expect(result).to_not be_empty
|
91
|
+
end
|
92
|
+
|
93
|
+
it "can be deserialized to a symbol" do
|
94
|
+
result = subject
|
95
|
+
hash = PigeonHole.parse(result)
|
96
|
+
|
97
|
+
expect(symbolize_hash(hash)).to eq(expected)
|
98
|
+
end
|
99
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rspec'
|
3
|
+
|
4
|
+
require "#{Rake.application.original_dir}/lib/pigeon_hole"
|
5
|
+
|
6
|
+
include PigeonHole
|
7
|
+
|
8
|
+
def random_integer
|
9
|
+
rand(9999)
|
10
|
+
end
|
11
|
+
|
12
|
+
def random_time
|
13
|
+
Time.now - random_integer
|
14
|
+
end
|
15
|
+
|
16
|
+
def random_date
|
17
|
+
Date.today - random_integer
|
18
|
+
end
|
19
|
+
|
20
|
+
def random_date_time
|
21
|
+
DateTime.now
|
22
|
+
end
|
23
|
+
|
24
|
+
def symbolize_hash(obj)
|
25
|
+
if obj.is_a?(Hash)
|
26
|
+
obj.inject({}) do |memo, (k,v)|
|
27
|
+
memo[k.to_sym] = symbolize_hash(v)
|
28
|
+
memo
|
29
|
+
end
|
30
|
+
else
|
31
|
+
obj
|
32
|
+
end
|
33
|
+
end
|
metadata
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: pigeon_hole
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Stephen Binns
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2016-07-13 00:00:00.000000000 Z
|
12
|
+
dependencies: []
|
13
|
+
description:
|
14
|
+
email:
|
15
|
+
executables: []
|
16
|
+
extensions: []
|
17
|
+
extra_rdoc_files: []
|
18
|
+
files:
|
19
|
+
- lib/pigeon_hole.rb
|
20
|
+
- lib/pigeon_hole/json_date.rb
|
21
|
+
- lib/pigeon_hole/json_date_time.rb
|
22
|
+
- lib/pigeon_hole/json_symbol.rb
|
23
|
+
- lib/pigeon_hole/json_time.rb
|
24
|
+
- lib/pigeon_hole/typed_json.rb
|
25
|
+
- spec/integration_spec.rb
|
26
|
+
- spec/spec_helper.rb
|
27
|
+
homepage: http://www.cronofy.com
|
28
|
+
licenses:
|
29
|
+
- MIT
|
30
|
+
metadata: {}
|
31
|
+
post_install_message:
|
32
|
+
rdoc_options: []
|
33
|
+
require_paths:
|
34
|
+
- lib
|
35
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
36
|
+
requirements:
|
37
|
+
- - ">="
|
38
|
+
- !ruby/object:Gem::Version
|
39
|
+
version: '0'
|
40
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
version: '0'
|
45
|
+
requirements: []
|
46
|
+
rubyforge_project:
|
47
|
+
rubygems_version: 2.6.1
|
48
|
+
signing_key:
|
49
|
+
specification_version: 4
|
50
|
+
summary: Opt-in typed serialization for complex JSON types
|
51
|
+
test_files:
|
52
|
+
- spec/integration_spec.rb
|
53
|
+
- spec/spec_helper.rb
|
54
|
+
has_rdoc:
|