tjson 0.4.0 → 0.5.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.
- checksums.yaml +4 -4
- data/.travis.yml +7 -1
- data/CHANGES.md +4 -0
- data/README.md +80 -28
- data/Rakefile +5 -0
- data/lib/tjson.rb +37 -2
- data/lib/tjson/datatype.rb +7 -50
- data/lib/tjson/datatype/array.rb +4 -4
- data/lib/tjson/datatype/binary.rb +12 -15
- data/lib/tjson/datatype/{value.rb → boolean.rb} +4 -4
- data/lib/tjson/datatype/float.rb +3 -3
- data/lib/tjson/datatype/integer.rb +3 -3
- data/lib/tjson/datatype/object.rb +3 -3
- data/lib/tjson/datatype/set.rb +3 -3
- data/lib/tjson/datatype/string.rb +2 -2
- data/lib/tjson/datatype/timestamp.rb +2 -2
- data/lib/tjson/object.rb +1 -1
- data/lib/tjson/version.rb +1 -1
- metadata +15 -15
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: e9c267b98ee23f52126fd4ee7fcea4e2c83d904f
|
4
|
+
data.tar.gz: 7d1844da5a4491a0864b9ffbcded27899104bb03
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 52fc6e24de955cfbc76ad5933b8613c7550455e87362b1615d0dd53b86f1e002d543de083d881ddd8f730d13f0c3906c82200e9d0ef16f880bd87030107c59ac
|
7
|
+
data.tar.gz: 317419a6d6624ba43e117fbc13b109e8b7ba678588fcaa41493b52e07799c89c3272dd9356717034937d1dbb0c52bb343523d19a9bb432d9a67b636b68bd83d5
|
data/.travis.yml
CHANGED
@@ -4,16 +4,22 @@ before_install: gem install bundler
|
|
4
4
|
|
5
5
|
bundler_args: --without development doc
|
6
6
|
|
7
|
+
script: bundle exec rake ci
|
8
|
+
|
7
9
|
rvm:
|
10
|
+
- jruby-9.1.5.0
|
8
11
|
- 2.0
|
9
12
|
- 2.1
|
10
13
|
- 2.2
|
11
14
|
- 2.3.1
|
12
15
|
- 2.4.1
|
13
|
-
- jruby-9.1.5.0
|
14
16
|
|
15
17
|
matrix:
|
16
18
|
fast_finish: true
|
19
|
+
include:
|
20
|
+
# Only run RuboCop on the latest Ruby
|
21
|
+
- env: SUITE="rubocop"
|
22
|
+
rvm: 2.4.1
|
17
23
|
|
18
24
|
branches:
|
19
25
|
only:
|
data/CHANGES.md
CHANGED
data/README.md
CHANGED
@@ -1,8 +1,24 @@
|
|
1
1
|
# TJSON for Ruby [![Gem Version][gem-image]][gem-link] [![Build Status][build-image]][build-link] [![Code Climate][codeclimate-image]][codeclimate-link] [![MIT licensed][license-image]][license-link]
|
2
2
|
|
3
|
-
A Ruby implementation of TJSON: Tagged JSON with Rich Types.
|
3
|
+
A Ruby implementation of [TJSON]: Tagged JSON with Rich Types.
|
4
4
|
|
5
|
-
https://www.tjson.org
|
5
|
+
[TJSON]: https://www.tjson.org
|
6
|
+
|
7
|
+
```json
|
8
|
+
{
|
9
|
+
"array-example:A<O>": [
|
10
|
+
{
|
11
|
+
"string-example:s": "foobar",
|
12
|
+
"binary-data-example:d": "QklOQVJZ",
|
13
|
+
"float-example:f": 0.42,
|
14
|
+
"int-example:i": "42",
|
15
|
+
"timestamp-example:t": "2016-11-06T22:27:34Z",
|
16
|
+
"boolean-example:b": true
|
17
|
+
}
|
18
|
+
],
|
19
|
+
"set-example:S<i>": [1, 2, 3]
|
20
|
+
}
|
21
|
+
```
|
6
22
|
|
7
23
|
[gem-image]: https://badge.fury.io/rb/tjson.svg
|
8
24
|
[gem-link]: https://rubygems.org/gems/tjson
|
@@ -13,6 +29,30 @@ https://www.tjson.org
|
|
13
29
|
[license-image]: https://img.shields.io/badge/license-MIT-blue.svg
|
14
30
|
[license-link]: https://github.com/tjson/tjson-ruby/blob/master/LICENSE.txt
|
15
31
|
|
32
|
+
## Help and Discussion
|
33
|
+
|
34
|
+
Have questions? Want to suggest a feature or change?
|
35
|
+
|
36
|
+
* [TJSON Gitter]: web-based chat
|
37
|
+
* [TJSON Google Group]: join via web or email ([tjson+subscribe@googlegroups.com])
|
38
|
+
|
39
|
+
[TJSON Gitter]: https://gitter.im/tjson/Lobby
|
40
|
+
[TJSON Google Group]: https://groups.google.com/forum/#!forum/tjson
|
41
|
+
[tjson+subscribe@googlegroups.com]: mailto:tjson+subscribe@googlegroups.com
|
42
|
+
|
43
|
+
## Requirements
|
44
|
+
|
45
|
+
This library is tested against the following Ruby versions:
|
46
|
+
|
47
|
+
- 2.0
|
48
|
+
- 2.1
|
49
|
+
- 2.2
|
50
|
+
- 2.3
|
51
|
+
- 2.4
|
52
|
+
- jruby 9.1
|
53
|
+
|
54
|
+
Other Ruby versions may work, but are not officially supported.
|
55
|
+
|
16
56
|
## Installation
|
17
57
|
|
18
58
|
Add this line to your application's Gemfile:
|
@@ -29,9 +69,9 @@ Or install it yourself as:
|
|
29
69
|
|
30
70
|
$ gem install tjson
|
31
71
|
|
32
|
-
##
|
72
|
+
## API
|
33
73
|
|
34
|
-
###
|
74
|
+
### TJSON.parse
|
35
75
|
|
36
76
|
To parse a TJSON document, use the `TJSON.parse` method:
|
37
77
|
|
@@ -40,43 +80,55 @@ To parse a TJSON document, use the `TJSON.parse` method:
|
|
40
80
|
=> {"foo"=>"bar"}
|
41
81
|
```
|
42
82
|
|
43
|
-
|
44
|
-
|
45
|
-
* **Unicode Strings**: parsed as Ruby `String` with `Encoding::UTF_8`
|
46
|
-
* **Binary Data**: parsed as Ruby `String` with `Encoding::ASCII_8BIT` (a.k.a. `Encoding::BINARY`)
|
47
|
-
* **Integers**: parsed as Ruby `Integer` (Fixnum or Bignum)
|
48
|
-
* **Floats** (i.e. JSON number literals): parsed as Ruby `Float`
|
49
|
-
* **Timestamps**: parsed as Ruby `Time`
|
50
|
-
* **Arrays**: parsed as Ruby `Array`
|
51
|
-
* **Objects**: parsed as `TJSON::Object` (a subclass of `::Hash`)
|
52
|
-
|
53
|
-
### Generating
|
83
|
+
### TJSON.generate
|
54
84
|
|
55
85
|
To generate TJSON from Ruby objects, use the `TJSON.generate` method:
|
56
86
|
|
57
87
|
```ruby
|
58
88
|
puts TJSON.generate({"foo" => "bar"})
|
59
|
-
{"foo:s:"bar"}
|
89
|
+
# {"foo:s:"bar"}
|
60
90
|
```
|
61
91
|
|
62
92
|
For better formatting, use the `TJSON.pretty_generate` method:
|
63
93
|
|
64
94
|
```ruby
|
65
|
-
puts TJSON.pretty_generate({"array-example" => [{"string-example" => "foobar", "binary-example" => "BINARY".
|
66
|
-
{
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
}
|
95
|
+
puts TJSON.pretty_generate({"array-example" => [{"string-example" => "foobar", "binary-example" => "BINARY".b, "float-example" => 0.42, "int-example" => 42, "timestamp-example" => Time.now}]})
|
96
|
+
# {
|
97
|
+
# "array-example:A<O>": [
|
98
|
+
# {
|
99
|
+
# "string-example:s": "foobar",
|
100
|
+
# "binary-example:d": "QklOQVJZ",
|
101
|
+
# "float-example:f": 0.42,
|
102
|
+
# "int-example:i": "42",
|
103
|
+
# "timestamp-example:t": "2016-11-06T22:27:34Z"
|
104
|
+
# }
|
105
|
+
# ]
|
106
|
+
# }
|
77
107
|
```
|
78
108
|
|
109
|
+
## Type Conversions
|
110
|
+
|
111
|
+
The table below shows how TJSON tags map to Ruby types:
|
112
|
+
|
113
|
+
| Tag | Ruby Type |
|
114
|
+
|-----|------------------------------------------------------------------|
|
115
|
+
| `b` | `true` or `false` |
|
116
|
+
| `d` | `String` with `Encoding::ASCII_8BIT` (a.k.a. `Encoding::BINARY`) |
|
117
|
+
| `f` | `Float` |
|
118
|
+
| `i` | `Integer` (`Fixnum` or `Bignum` on Ruby <2.4 ) |
|
119
|
+
| `u` | `Integer` (`Fixnum` or `Bignum` on Ruby <2.4 ) |
|
120
|
+
| `s` | `String` with `Encoding::UTF_8` |
|
121
|
+
| `t` | `Time` |
|
122
|
+
| `A` | `Array` |
|
123
|
+
| `O` | `TJSON::Object` (a subclass of `::Hash`) |
|
124
|
+
| `S` | `Set` |
|
125
|
+
|
79
126
|
## Contributing
|
80
127
|
|
81
128
|
Bug reports and pull requests are welcome on GitHub at https://github.com/tjson/tjson-ruby
|
82
129
|
|
130
|
+
## License
|
131
|
+
|
132
|
+
Copyright (c) 2017 Tony Arcieri. Distributed under the MIT License. See
|
133
|
+
[LICENSE.txt](https://github.com/tjson/tjson-ruby/blob/master/LICENSE.txt)
|
134
|
+
for further details.
|
data/Rakefile
CHANGED
data/lib/tjson.rb
CHANGED
@@ -12,6 +12,16 @@ require "base64"
|
|
12
12
|
require "tjson/datatype"
|
13
13
|
require "tjson/object"
|
14
14
|
|
15
|
+
require "tjson/datatype/array"
|
16
|
+
require "tjson/datatype/boolean"
|
17
|
+
require "tjson/datatype/binary"
|
18
|
+
require "tjson/datatype/float"
|
19
|
+
require "tjson/datatype/integer"
|
20
|
+
require "tjson/datatype/object"
|
21
|
+
require "tjson/datatype/set"
|
22
|
+
require "tjson/datatype/string"
|
23
|
+
require "tjson/datatype/timestamp"
|
24
|
+
|
15
25
|
# Tagged JSON with Rich Types
|
16
26
|
module TJSON
|
17
27
|
# Base class of all TJSON errors
|
@@ -32,6 +42,31 @@ module TJSON
|
|
32
42
|
# Maximum allowed nesting (TODO: use TJSON-specified maximum)
|
33
43
|
MAX_NESTING = 100
|
34
44
|
|
45
|
+
# Reopen the DataType class (defined in tjson/datatype.rb)
|
46
|
+
class DataType
|
47
|
+
# Table of tag identifiers supported by TJSON
|
48
|
+
TAGS = {
|
49
|
+
# Object (non-scalar with self-describing types)
|
50
|
+
"O" => TJSON::DataType::Object.new(nil).freeze,
|
51
|
+
|
52
|
+
# Non-scalars
|
53
|
+
"A" => TJSON::DataType::Array,
|
54
|
+
"S" => TJSON::DataType::Set,
|
55
|
+
|
56
|
+
# Scalars
|
57
|
+
"b" => TJSON::DataType::Boolean.new.freeze,
|
58
|
+
"d" => TJSON::DataType::Binary64.new.freeze,
|
59
|
+
"d16" => TJSON::DataType::Binary16.new.freeze,
|
60
|
+
"d32" => TJSON::DataType::Binary32.new.freeze,
|
61
|
+
"d64" => TJSON::DataType::Binary64.new.freeze,
|
62
|
+
"f" => TJSON::DataType::Float.new.freeze,
|
63
|
+
"i" => TJSON::DataType::SignedInt.new.freeze,
|
64
|
+
"s" => TJSON::DataType::String.new.freeze,
|
65
|
+
"t" => TJSON::DataType::Timestamp.new.freeze,
|
66
|
+
"u" => TJSON::DataType::UnsignedInt.new.freeze
|
67
|
+
}.freeze
|
68
|
+
end
|
69
|
+
|
35
70
|
# Parse the given UTF-8 string as TJSON
|
36
71
|
#
|
37
72
|
# @param string [String] TJSON string to be parsed
|
@@ -80,7 +115,7 @@ module TJSON
|
|
80
115
|
# @return [String] serialized TJSON
|
81
116
|
def self.generate(obj)
|
82
117
|
raise TypeError, "toplevel type must be a Hash" unless obj.is_a?(Hash)
|
83
|
-
JSON.generate(TJSON::DataType.
|
118
|
+
JSON.generate(TJSON::DataType.encode(obj))
|
84
119
|
end
|
85
120
|
|
86
121
|
# Generate TJSON from a Ruby Hash (TJSON only allows objects as toplevel values)
|
@@ -89,6 +124,6 @@ module TJSON
|
|
89
124
|
# @return [String] serialized TJSON
|
90
125
|
def self.pretty_generate(obj)
|
91
126
|
raise TypeError, "toplevel type must be a Hash" unless obj.is_a?(Hash)
|
92
|
-
JSON.pretty_generate(TJSON::DataType.
|
127
|
+
JSON.pretty_generate(TJSON::DataType.encode(obj))
|
93
128
|
end
|
94
129
|
end
|
data/lib/tjson/datatype.rb
CHANGED
@@ -31,38 +31,34 @@ module TJSON
|
|
31
31
|
when Hash then self["O"]
|
32
32
|
when ::Array then TJSON::DataType::Array.identify_type(obj)
|
33
33
|
when ::Set then TJSON::DataType::Set.identify_type(obj)
|
34
|
-
when ::String, Symbol then obj.encoding == Encoding::BINARY ? self["
|
34
|
+
when ::String, Symbol then obj.encoding == Encoding::BINARY ? self["d"] : self["s"]
|
35
35
|
when ::Integer then self["i"]
|
36
36
|
when ::Float then self["f"]
|
37
37
|
when ::TrueClass then self["v"]
|
38
|
-
when ::FalseClass then self["
|
38
|
+
when ::FalseClass then self["d"]
|
39
39
|
when ::Time, ::DateTime then self["t"]
|
40
40
|
else raise TypeError, "don't know how to serialize #{obj.class} as TJSON"
|
41
41
|
end
|
42
42
|
end
|
43
43
|
|
44
|
-
def self.
|
45
|
-
identify_type(obj).
|
44
|
+
def self.encode(obj)
|
45
|
+
identify_type(obj).encode(obj)
|
46
46
|
end
|
47
47
|
|
48
48
|
def tag
|
49
49
|
raise NotImplementError, "no #tag defined for #{self.class}"
|
50
50
|
end
|
51
51
|
|
52
|
-
def
|
53
|
-
raise NotImplementedError, "#{self.class} does not implement #
|
52
|
+
def decode(_value)
|
53
|
+
raise NotImplementedError, "#{self.class} does not implement #decode"
|
54
54
|
end
|
55
55
|
|
56
|
-
def
|
56
|
+
def encode(_value)
|
57
57
|
raise NotImplementedError, "#{self.class} does not implement #genreate"
|
58
58
|
end
|
59
59
|
|
60
60
|
# Scalar types
|
61
61
|
class Scalar < TJSON::DataType
|
62
|
-
def scalar?
|
63
|
-
true
|
64
|
-
end
|
65
|
-
|
66
62
|
def inspect
|
67
63
|
"#<#{self.class}>"
|
68
64
|
end
|
@@ -80,48 +76,9 @@ module TJSON
|
|
80
76
|
"#<#{self.class}<#{@inner_type.inspect}>>"
|
81
77
|
end
|
82
78
|
|
83
|
-
def scalar?
|
84
|
-
false
|
85
|
-
end
|
86
|
-
|
87
79
|
def ==(other)
|
88
80
|
self.class == other.class && inner_type == other.inner_type
|
89
81
|
end
|
90
82
|
end
|
91
|
-
|
92
|
-
# Numbers
|
93
|
-
class Number < Scalar; end
|
94
83
|
end
|
95
84
|
end
|
96
|
-
|
97
|
-
require "tjson/datatype/array"
|
98
|
-
require "tjson/datatype/binary"
|
99
|
-
require "tjson/datatype/float"
|
100
|
-
require "tjson/datatype/integer"
|
101
|
-
require "tjson/datatype/set"
|
102
|
-
require "tjson/datatype/string"
|
103
|
-
require "tjson/datatype/timestamp"
|
104
|
-
require "tjson/datatype/object"
|
105
|
-
require "tjson/datatype/value"
|
106
|
-
|
107
|
-
# TJSON does not presently support user-extensible types
|
108
|
-
TJSON::DataType::TAGS = {
|
109
|
-
# Object (non-scalar with self-describing types)
|
110
|
-
"O" => TJSON::DataType::Object.new(nil).freeze,
|
111
|
-
|
112
|
-
# Non-scalars
|
113
|
-
"A" => TJSON::DataType::Array,
|
114
|
-
"S" => TJSON::DataType::Set,
|
115
|
-
|
116
|
-
# Scalars
|
117
|
-
"b" => TJSON::DataType::Binary64.new.freeze,
|
118
|
-
"b16" => TJSON::DataType::Binary16.new.freeze,
|
119
|
-
"b32" => TJSON::DataType::Binary32.new.freeze,
|
120
|
-
"b64" => TJSON::DataType::Binary64.new.freeze,
|
121
|
-
"f" => TJSON::DataType::Float.new.freeze,
|
122
|
-
"i" => TJSON::DataType::SignedInt.new.freeze,
|
123
|
-
"s" => TJSON::DataType::String.new.freeze,
|
124
|
-
"t" => TJSON::DataType::Timestamp.new.freeze,
|
125
|
-
"u" => TJSON::DataType::UnsignedInt.new.freeze,
|
126
|
-
"v" => TJSON::DataType::Value.new.freeze
|
127
|
-
}.freeze
|
data/lib/tjson/datatype/array.rb
CHANGED
@@ -21,16 +21,16 @@ module TJSON
|
|
21
21
|
"A<#{@inner_type.tag}>"
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def decode(array)
|
25
25
|
raise TJSON::TypeError, "expected Array, got #{array.class}" unless array.is_a?(::Array)
|
26
26
|
|
27
|
-
return array.map! { |o| @inner_type.
|
27
|
+
return array.map! { |o| @inner_type.decode(o) } if @inner_type
|
28
28
|
return array if array.empty?
|
29
29
|
raise TJSON::ParseError, "no inner type specified for non-empty array: #{array.inspect}"
|
30
30
|
end
|
31
31
|
|
32
|
-
def
|
33
|
-
array.map { |o| TJSON::DataType.
|
32
|
+
def encode(array)
|
33
|
+
array.map { |o| TJSON::DataType.encode(o) }
|
34
34
|
end
|
35
35
|
end
|
36
36
|
end
|
@@ -2,16 +2,13 @@
|
|
2
2
|
|
3
3
|
module TJSON
|
4
4
|
class DataType
|
5
|
-
# Binary Data
|
6
|
-
class Binary < Scalar; end
|
7
|
-
|
8
5
|
# Base16-serialized binary data
|
9
|
-
class Binary16 <
|
6
|
+
class Binary16 < Scalar
|
10
7
|
def tag
|
11
|
-
"
|
8
|
+
"d16"
|
12
9
|
end
|
13
10
|
|
14
|
-
def
|
11
|
+
def decode(str)
|
15
12
|
raise TJSON::TypeError, "expected String, got #{str.class}: #{str.inspect}" unless str.is_a?(::String)
|
16
13
|
raise TJSON::ParseError, "base16 must be lower case: #{str.inspect}" if str =~ /[A-F]/
|
17
14
|
raise TJSON::ParseError, "invalid base16: #{str.inspect}" unless str =~ /\A[a-f0-9]*\z/
|
@@ -19,18 +16,18 @@ module TJSON
|
|
19
16
|
[str].pack("H*")
|
20
17
|
end
|
21
18
|
|
22
|
-
def
|
19
|
+
def encode(binary)
|
23
20
|
binary.unpack("H*").first
|
24
21
|
end
|
25
22
|
end
|
26
23
|
|
27
24
|
# Base32-serialized binary data
|
28
|
-
class Binary32 <
|
25
|
+
class Binary32 < Scalar
|
29
26
|
def tag
|
30
|
-
"
|
27
|
+
"d32"
|
31
28
|
end
|
32
29
|
|
33
|
-
def
|
30
|
+
def decode(str)
|
34
31
|
raise TJSON::TypeError, "expected String, got #{str.class}: #{str.inspect}" unless str.is_a?(::String)
|
35
32
|
raise TJSON::ParseError, "base32 must be lower case: #{str.inspect}" if str =~ /[A-Z]/
|
36
33
|
raise TJSON::ParseError, "padding disallowed: #{str.inspect}" if str.include?("=")
|
@@ -39,18 +36,18 @@ module TJSON
|
|
39
36
|
::Base32.decode(str.upcase).force_encoding(Encoding::BINARY)
|
40
37
|
end
|
41
38
|
|
42
|
-
def
|
39
|
+
def encode(binary)
|
43
40
|
Base32.encode(binary).downcase.delete("=")
|
44
41
|
end
|
45
42
|
end
|
46
43
|
|
47
44
|
# Base64-serialized binary data
|
48
|
-
class Binary64 <
|
45
|
+
class Binary64 < Scalar
|
49
46
|
def tag
|
50
|
-
"
|
47
|
+
"d64"
|
51
48
|
end
|
52
49
|
|
53
|
-
def
|
50
|
+
def decode(str)
|
54
51
|
raise TJSON::TypeError, "expected String, got #{str.class}: #{str.inspect}" unless str.is_a?(::String)
|
55
52
|
raise TJSON::ParseError, "base64url only: #{str.inspect}" if str =~ %r{\+|\/}
|
56
53
|
raise TJSON::ParseError, "padding disallowed: #{str.inspect}" if str.include?("=")
|
@@ -62,7 +59,7 @@ module TJSON
|
|
62
59
|
::Base64.urlsafe_decode64(str)
|
63
60
|
end
|
64
61
|
|
65
|
-
def
|
62
|
+
def encode(binary)
|
66
63
|
Base64.urlsafe_encode64(binary).delete("=")
|
67
64
|
end
|
68
65
|
end
|
@@ -3,18 +3,18 @@
|
|
3
3
|
module TJSON
|
4
4
|
class DataType
|
5
5
|
# Boolean Value
|
6
|
-
class
|
6
|
+
class Boolean < Scalar
|
7
7
|
def tag
|
8
|
-
"
|
8
|
+
"b"
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def decode(value)
|
12
12
|
raise TJSON::TypeError, "'null' is expressly disallowed in TJSON" if value.nil?
|
13
13
|
raise TJSON::TypeError, "not a boolean value: #{value.inspect}" unless [true, false].include?(value)
|
14
14
|
value
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def encode(value)
|
18
18
|
value
|
19
19
|
end
|
20
20
|
end
|
data/lib/tjson/datatype/float.rb
CHANGED
@@ -3,17 +3,17 @@
|
|
3
3
|
module TJSON
|
4
4
|
class DataType
|
5
5
|
# Floating point type
|
6
|
-
class Float <
|
6
|
+
class Float < Scalar
|
7
7
|
def tag
|
8
8
|
"f"
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def decode(float)
|
12
12
|
raise TJSON::TypeError, "not a floating point value: #{float.inspect}" unless float.is_a?(::Numeric)
|
13
13
|
float.to_f
|
14
14
|
end
|
15
15
|
|
16
|
-
def
|
16
|
+
def encode(float)
|
17
17
|
float.to_f
|
18
18
|
end
|
19
19
|
end
|
@@ -4,7 +4,7 @@ module TJSON
|
|
4
4
|
class DataType
|
5
5
|
# Base class of integer types
|
6
6
|
class Integer < Scalar
|
7
|
-
def
|
7
|
+
def encode(int)
|
8
8
|
# Integers are serialized as strings to sidestep the limits of some JSON parsers
|
9
9
|
int.to_s
|
10
10
|
end
|
@@ -16,7 +16,7 @@ module TJSON
|
|
16
16
|
"i"
|
17
17
|
end
|
18
18
|
|
19
|
-
def
|
19
|
+
def decode(str)
|
20
20
|
raise TJSON::TypeError, "expected String, got #{str.class}: #{str.inspect}" unless str.is_a?(::String)
|
21
21
|
raise TJSON::ParseError, "invalid integer: #{str.inspect}" unless str =~ /\A\-?(0|[1-9][0-9]*)\z/
|
22
22
|
|
@@ -34,7 +34,7 @@ module TJSON
|
|
34
34
|
"u"
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
37
|
+
def decode(str)
|
38
38
|
raise TJSON::TypeError, "expected String, got #{str.class}: #{str.inspect}" unless str.is_a?(::String)
|
39
39
|
raise TJSON::ParseError, "invalid integer: #{str.inspect}" unless str =~ /\A(0|[1-9][0-9]*)\z/
|
40
40
|
|
@@ -8,18 +8,18 @@ module TJSON
|
|
8
8
|
"O"
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def decode(obj)
|
12
12
|
raise TJSON::TypeError, "expected TJSON::Object, got #{obj.class}" unless obj.is_a?(TJSON::Object)
|
13
13
|
|
14
14
|
# Objects handle their own member conversions
|
15
15
|
obj
|
16
16
|
end
|
17
17
|
|
18
|
-
def
|
18
|
+
def encode(obj)
|
19
19
|
members = obj.map do |k, v|
|
20
20
|
raise TypeError, "expected String for key, got #{k.class}" unless k.is_a?(::String) || k.is_a?(Symbol)
|
21
21
|
type = TJSON::DataType.identify_type(v)
|
22
|
-
["#{k}:#{type.tag}", TJSON::DataType.
|
22
|
+
["#{k}:#{type.tag}", TJSON::DataType.encode(v)]
|
23
23
|
end
|
24
24
|
|
25
25
|
Hash[members]
|
data/lib/tjson/datatype/set.rb
CHANGED
@@ -21,11 +21,11 @@ module TJSON
|
|
21
21
|
"S<#{@inner_type.tag}>"
|
22
22
|
end
|
23
23
|
|
24
|
-
def
|
24
|
+
def decode(array)
|
25
25
|
raise TJSON::TypeError, "expected Array, got #{array.class}" unless array.is_a?(::Array)
|
26
26
|
|
27
27
|
if @inner_type
|
28
|
-
result = ::Set.new(array.map { |o| @inner_type.
|
28
|
+
result = ::Set.new(array.map { |o| @inner_type.decode(o) })
|
29
29
|
raise TJSON::ParseError, "set contains duplicate items" if result.size < array.size
|
30
30
|
return result
|
31
31
|
end
|
@@ -34,7 +34,7 @@ module TJSON
|
|
34
34
|
raise TJSON::ParseError, "no inner type specified for non-empty set: #{array.inspect}"
|
35
35
|
end
|
36
36
|
|
37
|
-
def
|
37
|
+
def encode(set)
|
38
38
|
set.map { |o| TJSON::DataType.generate(o) }
|
39
39
|
end
|
40
40
|
end
|
@@ -8,13 +8,13 @@ module TJSON
|
|
8
8
|
"s"
|
9
9
|
end
|
10
10
|
|
11
|
-
def
|
11
|
+
def decode(str)
|
12
12
|
raise TJSON::TypeError, "expected String, got #{str.class}: #{str.inspect}" unless str.is_a?(::String)
|
13
13
|
raise TJSON::EncodingError, "expected UTF-8, got #{str.encoding.inspect}" unless str.encoding == Encoding::UTF_8
|
14
14
|
str
|
15
15
|
end
|
16
16
|
|
17
|
-
def
|
17
|
+
def encode(obj)
|
18
18
|
obj.to_s
|
19
19
|
end
|
20
20
|
end
|
@@ -11,14 +11,14 @@ module TJSON
|
|
11
11
|
"t"
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def decode(str)
|
15
15
|
raise TJSON::TypeError, "expected String, got #{str.class}: #{str.inspect}" unless str.is_a?(::String)
|
16
16
|
raise TJSON::ParseError, "invalid timestamp: #{str.inspect}" unless str =~ TIMESTAMP_REGEX
|
17
17
|
|
18
18
|
::Time.iso8601(str)
|
19
19
|
end
|
20
20
|
|
21
|
-
def
|
21
|
+
def encode(timestamp)
|
22
22
|
timestamp.to_time.utc.iso8601
|
23
23
|
end
|
24
24
|
end
|
data/lib/tjson/object.rb
CHANGED
@@ -11,7 +11,7 @@ module TJSON
|
|
11
11
|
raise DuplicateNameError, "duplicate member name: #{result[:name].inspect}" if key?(result[:name])
|
12
12
|
|
13
13
|
type = TJSON::DataType.parse(result[:tag])
|
14
|
-
super(result[:name], type.
|
14
|
+
super(result[:name], type.decode(value))
|
15
15
|
end
|
16
16
|
end
|
17
17
|
end
|
data/lib/tjson/version.rb
CHANGED
metadata
CHANGED
@@ -1,41 +1,41 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: tjson
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tony Arcieri
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2017-04-
|
11
|
+
date: 2017-04-23 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: base32
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '0.3'
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
|
-
- -
|
24
|
+
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0.3'
|
27
27
|
- !ruby/object:Gem::Dependency
|
28
28
|
name: bundler
|
29
29
|
requirement: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
31
|
-
- - ~>
|
31
|
+
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '1.13'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
|
-
- - ~>
|
38
|
+
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '1.13'
|
41
41
|
description: A JSON-compatible serialization format with rich type annotations
|
@@ -45,12 +45,12 @@ executables: []
|
|
45
45
|
extensions: []
|
46
46
|
extra_rdoc_files: []
|
47
47
|
files:
|
48
|
-
- .gitignore
|
49
|
-
- .rakeTasks
|
50
|
-
- .rspec
|
51
|
-
- .rubocop.yml
|
52
|
-
- .ruby-version
|
53
|
-
- .travis.yml
|
48
|
+
- ".gitignore"
|
49
|
+
- ".rakeTasks"
|
50
|
+
- ".rspec"
|
51
|
+
- ".rubocop.yml"
|
52
|
+
- ".ruby-version"
|
53
|
+
- ".travis.yml"
|
54
54
|
- CHANGES.md
|
55
55
|
- Gemfile
|
56
56
|
- Guardfile
|
@@ -61,13 +61,13 @@ files:
|
|
61
61
|
- lib/tjson/datatype.rb
|
62
62
|
- lib/tjson/datatype/array.rb
|
63
63
|
- lib/tjson/datatype/binary.rb
|
64
|
+
- lib/tjson/datatype/boolean.rb
|
64
65
|
- lib/tjson/datatype/float.rb
|
65
66
|
- lib/tjson/datatype/integer.rb
|
66
67
|
- lib/tjson/datatype/object.rb
|
67
68
|
- lib/tjson/datatype/set.rb
|
68
69
|
- lib/tjson/datatype/string.rb
|
69
70
|
- lib/tjson/datatype/timestamp.rb
|
70
|
-
- lib/tjson/datatype/value.rb
|
71
71
|
- lib/tjson/object.rb
|
72
72
|
- lib/tjson/version.rb
|
73
73
|
- tjson.gemspec
|
@@ -81,12 +81,12 @@ require_paths:
|
|
81
81
|
- lib
|
82
82
|
required_ruby_version: !ruby/object:Gem::Requirement
|
83
83
|
requirements:
|
84
|
-
- -
|
84
|
+
- - ">="
|
85
85
|
- !ruby/object:Gem::Version
|
86
86
|
version: '2.0'
|
87
87
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
88
88
|
requirements:
|
89
|
-
- -
|
89
|
+
- - ">="
|
90
90
|
- !ruby/object:Gem::Version
|
91
91
|
version: '0'
|
92
92
|
requirements: []
|