protojson 0.1.0 → 0.2.0
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 +1 -3
- data/README.md +24 -19
- data/Rakefile +10 -8
- data/examples/addressbook.pb.rb +70 -0
- data/examples/addressbook.proto +37 -0
- data/examples/addressbook2.pb.rb +56 -0
- data/examples/example.rb +54 -0
- data/examples/main.rb +50 -0
- data/{spec → examples}/person +0 -0
- data/examples/repeated.pb.rb +32 -0
- data/examples/repeated.proto +12 -0
- data/examples/simple.pb.rb +23 -0
- data/examples/simple.proto +7 -0
- data/lib/protojson.rb +81 -3
- data/lib/protojson/codec/binary.rb +21 -0
- data/lib/protojson/codec/codec_interface.rb +15 -0
- data/lib/protojson/codec/hash.rb +121 -0
- data/lib/protojson/codec/json.rb +24 -0
- data/lib/protojson/codec/json_indexed.rb +85 -0
- data/lib/protojson/codec/json_tag_map.rb +25 -0
- data/lib/protojson/version.rb +1 -1
- data/protojson.gemspec +17 -10
- data/spec/codec_binary_spec.rb +150 -0
- data/spec/codec_json_hash_tag_spec.rb +179 -0
- data/spec/codec_json_indexed_spec.rb +182 -0
- data/spec/codec_json_spec.rb +153 -0
- data/spec/codecs_registry_spec.rb +85 -0
- metadata +75 -18
- data/spec/main.rb +0 -55
data/lib/protojson.rb
CHANGED
@@ -1,6 +1,84 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
%W(binary json hash json_indexed json_tag_map).each { |codec|
|
2
|
+
require "protojson/codec/#{codec}"
|
3
|
+
}
|
3
4
|
|
4
5
|
module Protojson
|
5
|
-
|
6
|
+
|
7
|
+
class << self
|
8
|
+
|
9
|
+
# Key name - Codec value
|
10
|
+
def []=(codec_name = nil, codec = nil)
|
11
|
+
codec_name.is_a?(String) and codec_name.downcase!
|
12
|
+
|
13
|
+
unless codec_name.nil? # default codec
|
14
|
+
unless codec_name.is_a?(Symbol)
|
15
|
+
if codec_name.respond_to?(:to_sym)
|
16
|
+
codec_name = codec_name.to_sym
|
17
|
+
else
|
18
|
+
raise Exception, "Only symbols allowed as codec names"
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
if codec.nil? # unregister codec
|
24
|
+
codecs.delete(codec_name)
|
25
|
+
else # register codec
|
26
|
+
!codec.is_a? Protojson::Codec::CodecInterface and raise Exception, "codec should include Protojson::Codec::CodecInterface"
|
27
|
+
codecs[codec_name] = codec
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
# Returns the codec specified or the default one if no attribute is defined
|
32
|
+
def [](codec = nil)
|
33
|
+
codec.is_a?(Protojson::Codec::CodecInterface) and return codec
|
34
|
+
codec.is_a?(Symbol) or codec.nil? and return codecs[codec]
|
35
|
+
raise "Invalid codec #{codec}. It should either implement Protojson::Codec::CodecInterface or be a symbol"
|
36
|
+
end
|
37
|
+
|
38
|
+
# Initializes the codecs Hash
|
39
|
+
def codecs
|
40
|
+
@codecs ||= (
|
41
|
+
# While accessing the Hash, if the key does not exist, throws an exception
|
42
|
+
h = Hash.new { |hash, key|
|
43
|
+
hash.has_key?(key) and return hash[key]
|
44
|
+
!key.nil? and raise Exception, "Undefined codec #{key}"
|
45
|
+
h[nil] = Protojson::Codec::Binary
|
46
|
+
}
|
47
|
+
# default value is Binary codec
|
48
|
+
h[nil] = Protojson::Codec::Binary
|
49
|
+
h[:hash] = Protojson::Codec::Hash
|
50
|
+
h[:indexed] = Protojson::Codec::JsonIndexed
|
51
|
+
h[:json] = Protojson::Codec::Json
|
52
|
+
h[:tag_map] = Protojson::Codec::JsonTagMap
|
53
|
+
h
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
def set_default_codec(codec)
|
58
|
+
# fetch codec from Hash if codec name received
|
59
|
+
if codec.is_a?(Symbol) or codec.is_a?(String)
|
60
|
+
codec = Protojson[codec]
|
61
|
+
end
|
62
|
+
|
63
|
+
# set default codec
|
64
|
+
puts codec.is_a?(Protojson::Codec::CodecInterface)
|
65
|
+
if codec.is_a?(Protojson::Codec::CodecInterface)
|
66
|
+
codecs[nil] = codec
|
67
|
+
else
|
68
|
+
raise Exception, 'Codec must implement Protojson::Codec::CodecInterface'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def encode(message, codec = nil)
|
73
|
+
codec = send("[]".to_sym, codec)
|
74
|
+
codec.encode(message)
|
75
|
+
end
|
76
|
+
|
77
|
+
def decode(message, data, codec = nil)
|
78
|
+
codec = send("[]".to_sym, codec) # fetch default codec if none given
|
79
|
+
codec.decode(message, data)
|
80
|
+
end
|
81
|
+
|
82
|
+
end
|
83
|
+
|
6
84
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'protojson/codec/codec_interface'
|
2
|
+
|
3
|
+
module Protojson
|
4
|
+
module Codec
|
5
|
+
class Binary
|
6
|
+
extend Protojson::Codec::CodecInterface
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
def encode(message)
|
11
|
+
message.serialize_to_string
|
12
|
+
end
|
13
|
+
|
14
|
+
def decode(message, data)
|
15
|
+
message.new.parse_from_string(data)
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Protojson
|
2
|
+
module Codec
|
3
|
+
module CodecInterface
|
4
|
+
|
5
|
+
def encode(message)
|
6
|
+
raise NotImplementedError, "#{self.class} should implement encode method"
|
7
|
+
end
|
8
|
+
|
9
|
+
def decode(message, data)
|
10
|
+
raise NotImplementedError, "#{self.class} should implement decode method"
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'protobuf/message/message'
|
2
|
+
require 'protobuf/message/field'
|
3
|
+
require 'protobuf/message/enum'
|
4
|
+
|
5
|
+
module Protojson
|
6
|
+
module Codec
|
7
|
+
class Hash
|
8
|
+
extend Protojson::Codec::CodecInterface
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
# Encode the message to a hash object defined as a collection for key/values
|
13
|
+
# where each element has:
|
14
|
+
# - key: field tag
|
15
|
+
# - value:
|
16
|
+
# - if field.is_a? message_field => field.value.serialized_to_hash
|
17
|
+
# - if field.is_a? enum_field => field.value.value
|
18
|
+
# - else => field.value
|
19
|
+
#
|
20
|
+
# @return [Hash] a specific Message encoded in an Hash object
|
21
|
+
def encode(message, encoding_key = :name)
|
22
|
+
raise NotInitializedError unless message.initialized?
|
23
|
+
# var to store the encoded message fields
|
24
|
+
result = {}
|
25
|
+
|
26
|
+
# lambda function that extract the field tag and value
|
27
|
+
# it's called recursively if value is a MessageField
|
28
|
+
field_value_to_string = lambda { |field, value|
|
29
|
+
field_value = \
|
30
|
+
if field.optional? && !message.has_field?(field.name)
|
31
|
+
''
|
32
|
+
else
|
33
|
+
case field
|
34
|
+
when Protobuf::Field::MessageField
|
35
|
+
if value.nil?
|
36
|
+
nil
|
37
|
+
else
|
38
|
+
encode(value, encoding_key)
|
39
|
+
end
|
40
|
+
when Protobuf::Field::EnumField
|
41
|
+
if value.is_a?(Protobuf::EnumValue)
|
42
|
+
value.value
|
43
|
+
else
|
44
|
+
value.to_i
|
45
|
+
end
|
46
|
+
else
|
47
|
+
value
|
48
|
+
end
|
49
|
+
end
|
50
|
+
return field.send(encoding_key), field_value
|
51
|
+
}
|
52
|
+
|
53
|
+
# per each message field create a new element in result var with
|
54
|
+
# key = field.tag and value = field.value
|
55
|
+
message.each_field do |field, value|
|
56
|
+
# create a vector if field is repeated
|
57
|
+
if field.repeated? && !value.empty?
|
58
|
+
key_value = []
|
59
|
+
key = nil
|
60
|
+
value.each do |v|
|
61
|
+
key, val = field_value_to_string.call(field, v) # always return the same key
|
62
|
+
key_value.push val
|
63
|
+
end
|
64
|
+
# field is not repeated but is not empty
|
65
|
+
elsif !field.repeated?
|
66
|
+
key, key_value = field_value_to_string.call(field, value)
|
67
|
+
# empty field, discard
|
68
|
+
else
|
69
|
+
next
|
70
|
+
end
|
71
|
+
# new element in result Hash
|
72
|
+
unless key_value.nil? or (key_value.respond_to?(:empty?) and key_value.empty?)
|
73
|
+
result[key.to_s] = key_value
|
74
|
+
end
|
75
|
+
end
|
76
|
+
result
|
77
|
+
end
|
78
|
+
|
79
|
+
# This method parses a JSON encoded message to the message object
|
80
|
+
def decode(message, data, decoding_key = :name)
|
81
|
+
|
82
|
+
message = message.new
|
83
|
+
|
84
|
+
# per each hash element:
|
85
|
+
data.each_pair { |key, value|
|
86
|
+
key = decoding_key.eql?(:tag) ? key.to_i : key.to_s
|
87
|
+
|
88
|
+
# get the field object using the key (field tag)
|
89
|
+
#field = message.get_field_by_tag(key.to_i)
|
90
|
+
field = message.send("get_field_by_#{decoding_key}".to_sym, key)
|
91
|
+
|
92
|
+
if field.nil?
|
93
|
+
# ignore unknown field
|
94
|
+
elsif field.repeated?
|
95
|
+
# create the element
|
96
|
+
array = message.__send__(field.name)
|
97
|
+
value.each { |val|
|
98
|
+
# if value is a complex field, create the object and parse the content
|
99
|
+
if field.is_a?(Protobuf::Field::MessageField)
|
100
|
+
instance = field.type
|
101
|
+
val = decode(instance, val, decoding_key)
|
102
|
+
end
|
103
|
+
# include each element in the parent element field
|
104
|
+
array.push(val)
|
105
|
+
}
|
106
|
+
else
|
107
|
+
# if value is a complex field, create the object and parse the content
|
108
|
+
if field.is_a?(Protobuf::Field::MessageField)
|
109
|
+
instance = field.type
|
110
|
+
value = decode(instance, value, decoding_key)
|
111
|
+
end
|
112
|
+
# set the message field
|
113
|
+
message.__send__("#{field.name}=", value)
|
114
|
+
end
|
115
|
+
}
|
116
|
+
message
|
117
|
+
end
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
require 'protojson/codec/codec_interface'
|
4
|
+
|
5
|
+
module Protojson
|
6
|
+
module Codec
|
7
|
+
class Json
|
8
|
+
extend Protojson::Codec::CodecInterface
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def encode(message)
|
13
|
+
Protojson::Codec::Hash.encode(message).to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
def decode(message, data)
|
17
|
+
data.is_a?(String) and data = ActiveSupport::JSON.decode(data)
|
18
|
+
Protojson::Codec::Hash.decode(message, data)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
require 'protojson/codec/codec_interface'
|
4
|
+
|
5
|
+
module Protojson
|
6
|
+
module Codec
|
7
|
+
class JsonIndexed
|
8
|
+
extend Protojson::Codec::CodecInterface
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def encode(message)
|
13
|
+
data = Protojson::Codec::Hash.encode(message, :tag)
|
14
|
+
serialize_hash_to_indexed(data)
|
15
|
+
end
|
16
|
+
|
17
|
+
def decode(message, data)
|
18
|
+
data.is_a?(String) and data = ActiveSupport::JSON.decode(data)
|
19
|
+
|
20
|
+
values = parse_indexed_to_hash(message.new, data)
|
21
|
+
Protojson::Codec::Hash.decode(message, values, :tag)
|
22
|
+
end
|
23
|
+
|
24
|
+
# This class method serializes a Hash
|
25
|
+
def serialize_hash_to_indexed(value)
|
26
|
+
!value.is_a?(::Hash) and raise ArgumentError, "value must be a hash"
|
27
|
+
|
28
|
+
# index value
|
29
|
+
index = ""
|
30
|
+
index.respond_to?(:force_encoding) and index.force_encoding("UTF-8") # 1.9.2
|
31
|
+
# field values
|
32
|
+
result = []
|
33
|
+
value.each_pair { |key, value|
|
34
|
+
index << key.to_i+48 # ASCII integer. 1 => 49, ...
|
35
|
+
# recursive call if value is a Hash
|
36
|
+
if value.is_a?(::Hash)
|
37
|
+
value = serialize_hash_to_indexed(value)
|
38
|
+
# array => serializes each element
|
39
|
+
elsif value.is_a?(Array)
|
40
|
+
value.map! { |val|
|
41
|
+
if val.is_a?(::Hash)
|
42
|
+
serialize_hash_to_indexed(val)
|
43
|
+
else
|
44
|
+
val
|
45
|
+
end
|
46
|
+
}
|
47
|
+
end
|
48
|
+
# insert encoded value in Array
|
49
|
+
result.push value
|
50
|
+
}
|
51
|
+
# include index as first element
|
52
|
+
result.unshift(index)
|
53
|
+
end
|
54
|
+
|
55
|
+
# This method parses a INDEXED encoded message to a hash using
|
56
|
+
# message message as model.
|
57
|
+
# We need to know the specific message to decode to differenciate between
|
58
|
+
# vectors and message fields
|
59
|
+
def parse_indexed_to_hash(message, data)
|
60
|
+
values = {}
|
61
|
+
index = data.shift
|
62
|
+
index.each_codepoint { |tag|
|
63
|
+
tag = tag-48
|
64
|
+
field = message.get_field_by_tag(tag)
|
65
|
+
val = data.shift
|
66
|
+
|
67
|
+
if val.is_a?(Array) && field.is_a?(Protobuf::Field::MessageField)
|
68
|
+
if field.repeated?
|
69
|
+
val.map! { |v|
|
70
|
+
v = parse_indexed_to_hash(field.type, v)
|
71
|
+
}
|
72
|
+
else
|
73
|
+
val = parse_indexed_to_hash(field.type, val)
|
74
|
+
end
|
75
|
+
end
|
76
|
+
values[tag.to_s] = val
|
77
|
+
}
|
78
|
+
values
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support/core_ext'
|
2
|
+
|
3
|
+
require 'protojson/codec/codec_interface'
|
4
|
+
|
5
|
+
module Protojson
|
6
|
+
module Codec
|
7
|
+
class JsonTagMap
|
8
|
+
extend Protojson::Codec::CodecInterface
|
9
|
+
|
10
|
+
class << self
|
11
|
+
|
12
|
+
def encode(message)
|
13
|
+
Protojson::Codec::Hash.encode(message, :tag).to_json
|
14
|
+
end
|
15
|
+
|
16
|
+
def decode(message, data)
|
17
|
+
data.is_a?(String) and data = ActiveSupport::JSON.decode(data)
|
18
|
+
Protojson::Codec::Hash.decode(message, data, :tag)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/protojson/version.rb
CHANGED
data/protojson.gemspec
CHANGED
@@ -3,13 +3,13 @@ $:.push File.expand_path("../lib", __FILE__)
|
|
3
3
|
require "protojson/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name
|
7
|
-
s.version
|
8
|
-
s.platform
|
9
|
-
s.authors
|
10
|
-
s.email
|
11
|
-
s.homepage
|
12
|
-
s.summary
|
6
|
+
s.name = "protojson"
|
7
|
+
s.version = Protojson::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Juan de Bravo", "Ivan -DrSlump- Montes"]
|
10
|
+
s.email = ["juandebravo@gmail.com", "drslump@pollinimini.net"]
|
11
|
+
s.homepage = ""
|
12
|
+
s.summary = %q{Ruby extension to ruby-protobuf to enable three new encodings}
|
13
13
|
s.description = %q{A Ruby gem for Google's Protocol Buffers messages using three different encodings JSON
|
14
14
|
based syntax instead of the original binary protocol. Supported formats
|
15
15
|
|
@@ -25,10 +25,17 @@ Gem::Specification.new do |s|
|
|
25
25
|
|
26
26
|
s.rubyforge_project = "protojson"
|
27
27
|
|
28
|
-
s.files
|
28
|
+
s.files = `git ls-files`.split("\n")
|
29
29
|
s.files.delete("Gemfile.lock")
|
30
30
|
s.files.delete(".gitignore")
|
31
|
-
s.test_files
|
32
|
-
s.executables
|
31
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
32
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map { |f| File.basename(f) }
|
33
33
|
s.require_paths = ["lib"]
|
34
|
+
|
35
|
+
s.add_dependency('ruby_protobuf', '~>0.4.10')
|
36
|
+
s.add_dependency('activesupport', '~>3.0.5')
|
37
|
+
s.add_dependency('i18n', '~>0.5.0')
|
38
|
+
|
39
|
+
s.add_development_dependency("rspec")
|
40
|
+
|
34
41
|
end
|
@@ -0,0 +1,150 @@
|
|
1
|
+
# -*- coding: UTF-8 -*-
|
2
|
+
|
3
|
+
#$:.unshift File.join(File.dirname(__FILE__), '..', 'lib')
|
4
|
+
$:.unshift File.join(File.dirname(__FILE__), '..')
|
5
|
+
|
6
|
+
require 'protojson'
|
7
|
+
|
8
|
+
require 'examples/simple.pb'
|
9
|
+
require 'examples/repeated.pb'
|
10
|
+
require 'examples/addressbook.pb'
|
11
|
+
|
12
|
+
describe Protojson::Codec::Binary do
|
13
|
+
before(:all) do
|
14
|
+
Protojson.set_default_codec(Protojson::Codec::Binary)
|
15
|
+
end
|
16
|
+
|
17
|
+
context "simple message" do
|
18
|
+
|
19
|
+
it "should encode properly when two required attributes provided" do
|
20
|
+
simple = Examples::Simple.new
|
21
|
+
simple.foo = "Foo"
|
22
|
+
simple.bar = 1000
|
23
|
+
decoded = Protojson.decode(Examples::Simple, Protojson.encode(simple))
|
24
|
+
decoded.foo.should eql("Foo")
|
25
|
+
decoded.bar.should eql(1000)
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should encode properly when two required attributes and one optional attribute provided" do
|
29
|
+
simple = Examples::Simple.new
|
30
|
+
simple.foo = "Foo"
|
31
|
+
simple.bar = 1000
|
32
|
+
simple.baz = "Bazz"
|
33
|
+
decoded = Protojson.decode(Examples::Simple, Protojson.encode(simple))
|
34
|
+
decoded.foo.should eql("Foo")
|
35
|
+
decoded.bar.should eql(1000)
|
36
|
+
decoded.baz.should eql("Bazz")
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
context "repeated message" do
|
41
|
+
|
42
|
+
it "should encode properly when the string field has more than one value" do
|
43
|
+
repeated = Examples::Repeated.new
|
44
|
+
repeated.string << "one"
|
45
|
+
repeated.string << "two"
|
46
|
+
repeated.string << "three"
|
47
|
+
decoded = Protojson.decode(Examples::Repeated, Protojson.encode(repeated))
|
48
|
+
decoded.string.length.should eql(3)
|
49
|
+
decoded.string[0].should eql("one")
|
50
|
+
decoded.string[1].should eql("two")
|
51
|
+
decoded.string[2].should eql("three")
|
52
|
+
end
|
53
|
+
|
54
|
+
it "should encode properly when the int field has more than one value" do
|
55
|
+
repeated = Examples::Repeated.new
|
56
|
+
repeated.int << 1
|
57
|
+
repeated.int << 2
|
58
|
+
repeated.int << 3
|
59
|
+
decoded = Protojson.decode(Examples::Repeated, Protojson.encode(repeated))
|
60
|
+
decoded.int.length.should eql(3)
|
61
|
+
(0..2).each{|i|
|
62
|
+
decoded.int[i].should eql(i+1)
|
63
|
+
}
|
64
|
+
end
|
65
|
+
|
66
|
+
it "should encode properly when both int and string fields has more than one value" do
|
67
|
+
repeated = Examples::Repeated.new
|
68
|
+
repeated.string << "one"
|
69
|
+
repeated.string << "two"
|
70
|
+
repeated.string << "three"
|
71
|
+
repeated.int << 1
|
72
|
+
repeated.int << 2
|
73
|
+
repeated.int << 3
|
74
|
+
decoded = Protojson.decode(Examples::Repeated, Protojson.encode(repeated))
|
75
|
+
decoded.string.length.should eql(3)
|
76
|
+
decoded.string[0].should eql("one")
|
77
|
+
decoded.string[1].should eql("two")
|
78
|
+
decoded.string[2].should eql("three")
|
79
|
+
decoded.int.length.should eql(3)
|
80
|
+
(0..2).each{|i|
|
81
|
+
decoded.int[i].should eql(i+1)
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
it "should encode properly when the nested field has more than one value" do
|
86
|
+
repeated = Examples::Repeated.new
|
87
|
+
(1..3).each { |id|
|
88
|
+
nested = Examples::Repeated::Nested.new
|
89
|
+
nested.id = id
|
90
|
+
repeated.nested << nested
|
91
|
+
}
|
92
|
+
decoded = Protojson.decode(Examples::Repeated, Protojson.encode(repeated))
|
93
|
+
decoded.nested.length.should eql(3)
|
94
|
+
(0..2).each{|i|
|
95
|
+
decoded.nested[i].should be_instance_of Examples::Repeated::Nested
|
96
|
+
decoded.nested[i].id.should eql(i+1)
|
97
|
+
}
|
98
|
+
end
|
99
|
+
|
100
|
+
end
|
101
|
+
|
102
|
+
context "complex message" do
|
103
|
+
it "should work!! :)" do
|
104
|
+
book = Examples::AddressBook.new
|
105
|
+
person = Examples::Person.new
|
106
|
+
person.name = 'John Doe'
|
107
|
+
person.id = 2051
|
108
|
+
person.email = "john.doe@gmail.com"
|
109
|
+
phone = Examples::Person::PhoneNumber.new
|
110
|
+
phone.number = '1231231212'
|
111
|
+
phone.type = Examples::Person::PhoneType::HOME
|
112
|
+
person.phone << phone
|
113
|
+
phone = Examples::Person::PhoneNumber.new
|
114
|
+
phone.number = '55512321312'
|
115
|
+
phone.type = Examples::Person::PhoneType::MOBILE
|
116
|
+
person.phone << phone
|
117
|
+
book.person << person
|
118
|
+
|
119
|
+
person = Examples::Person.new
|
120
|
+
person.name = "Ivan Montes"
|
121
|
+
person.id = 23
|
122
|
+
person.email = "drslump@pollinimini.net"
|
123
|
+
phone = Examples::Person::PhoneNumber.new
|
124
|
+
phone.number = '3493123123'
|
125
|
+
phone.type = Examples::Person::PhoneType::WORK
|
126
|
+
person.phone << phone
|
127
|
+
book.person << person
|
128
|
+
|
129
|
+
person = Examples::Person.new
|
130
|
+
person.name = "Juan de Bravo"
|
131
|
+
person.id = 24
|
132
|
+
person.email = "juan@pollinimini.net"
|
133
|
+
phone = Examples::Person::PhoneNumber.new
|
134
|
+
phone.number = '3493123124'
|
135
|
+
phone.type = Examples::Person::PhoneType::WORK
|
136
|
+
person.phone << phone
|
137
|
+
book.person << person
|
138
|
+
|
139
|
+
decoded = Protojson.decode(Examples::AddressBook, Protojson.encode(book))
|
140
|
+
|
141
|
+
decoded.person.length.should eql 3
|
142
|
+
decoded.person[0].name.should eql "John Doe"
|
143
|
+
decoded.person[1].name.should eql "Ivan Montes"
|
144
|
+
decoded.person[2].name.should eql "Juan de Bravo"
|
145
|
+
decoded.person[0].phone[1].number.should eql "55512321312"
|
146
|
+
end
|
147
|
+
|
148
|
+
end
|
149
|
+
|
150
|
+
end
|