opal-json 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.
- data/README.md +1 -0
- data/lib/opal/json.rb +132 -0
- data/spec/parse_spec.rb +31 -0
- data/spec/to_json_spec.rb +53 -0
- metadata +51 -0
data/README.md
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
# JSON for Opal
|
data/lib/opal/json.rb
ADDED
@@ -0,0 +1,132 @@
|
|
1
|
+
module JSON
|
2
|
+
def self.parse(source)
|
3
|
+
%x{
|
4
|
+
var json = json_parse(source);
|
5
|
+
return to_opal(json);
|
6
|
+
}
|
7
|
+
end
|
8
|
+
|
9
|
+
%x{
|
10
|
+
var json_parse;
|
11
|
+
var cx = /[\\u0000\\u00ad\\u0600-\\u0604\\u070f\\u17b4\\u17b5\\u200c-\\u200f\\u2028-\\u202f\\u2060-\\u206f\\ufeff\\ufff0-\\uffff]/g;
|
12
|
+
|
13
|
+
if (typeof JSON !== 'undefined') {
|
14
|
+
json_parse = JSON.parse;
|
15
|
+
}
|
16
|
+
else {
|
17
|
+
json_parse = function(text) {
|
18
|
+
console.log("using opal's JSON.parse");
|
19
|
+
|
20
|
+
text = String(text);
|
21
|
+
cx.lastIndex = 0;
|
22
|
+
|
23
|
+
if (cx.test(text)) {
|
24
|
+
text = text.replace(cx, function(a) {
|
25
|
+
return '\\\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
|
26
|
+
});
|
27
|
+
}
|
28
|
+
|
29
|
+
if (/^[\\],:{}\\s]*$/
|
30
|
+
.test(text.replace(/\\\\(?:["\\\\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
|
31
|
+
.replace(/"[^"\\\\\\n\\r]*"|true|false|null|-?\\d+(?:\\.\\d*)?(?:[eE][+\\-]?\\d+)?/g, ']')
|
32
|
+
.replace(/(?:^|:|,)(?:\\s*\\[)+/g, ''))) {
|
33
|
+
|
34
|
+
return eval('(' + text + ')');
|
35
|
+
}
|
36
|
+
|
37
|
+
throw new SyntaxError('JSON.parse');
|
38
|
+
};
|
39
|
+
}
|
40
|
+
|
41
|
+
|
42
|
+
function to_opal(value) {
|
43
|
+
switch (typeof value) {
|
44
|
+
case 'string':
|
45
|
+
return value;
|
46
|
+
|
47
|
+
case 'number':
|
48
|
+
return value;
|
49
|
+
|
50
|
+
case 'boolean':
|
51
|
+
return !!value;
|
52
|
+
|
53
|
+
case 'null':
|
54
|
+
return nil;
|
55
|
+
|
56
|
+
case 'object':
|
57
|
+
if (!value) return nil;
|
58
|
+
|
59
|
+
if (Object.prototype.toString.apply(value) === '[object Array]') {
|
60
|
+
var arr = [];
|
61
|
+
|
62
|
+
for (var i = 0, ii = value.length; i < ii; i++) {
|
63
|
+
arr.push(to_opal(value[i]));
|
64
|
+
}
|
65
|
+
|
66
|
+
return arr;
|
67
|
+
}
|
68
|
+
else {
|
69
|
+
var hash = #{ {} }, v, map = hash.map;
|
70
|
+
|
71
|
+
for (var k in value) {
|
72
|
+
if (Object.hasOwnProperty.call(value, k)) {
|
73
|
+
v = to_opal(value[k]);
|
74
|
+
map[k] = [k, v];
|
75
|
+
}
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
return hash;
|
80
|
+
}
|
81
|
+
};
|
82
|
+
}
|
83
|
+
end
|
84
|
+
|
85
|
+
module Kernel
|
86
|
+
def to_json; to_s.to_json; end
|
87
|
+
end
|
88
|
+
|
89
|
+
class Numeric
|
90
|
+
alias to_json to_s
|
91
|
+
end
|
92
|
+
|
93
|
+
class String
|
94
|
+
alias to_json inspect
|
95
|
+
end
|
96
|
+
|
97
|
+
class NilClass
|
98
|
+
def to_json; 'null'; end
|
99
|
+
end
|
100
|
+
|
101
|
+
class Boolean
|
102
|
+
def to_json; `this.valueOf() ? 'true' : 'false'`; end
|
103
|
+
end
|
104
|
+
|
105
|
+
class Array
|
106
|
+
def to_json
|
107
|
+
%x{
|
108
|
+
var result = [];
|
109
|
+
|
110
|
+
for (var i = 0, length = this.length; i < length; i++) {
|
111
|
+
result.push(#{`this[i]`.to_json});
|
112
|
+
}
|
113
|
+
|
114
|
+
return '[' + result.join(', ') + ']';
|
115
|
+
}
|
116
|
+
end
|
117
|
+
end
|
118
|
+
|
119
|
+
class Hash
|
120
|
+
def to_json
|
121
|
+
%x{
|
122
|
+
var parts = [], map = this.map, bucket;
|
123
|
+
|
124
|
+
for (var assoc in map) {
|
125
|
+
bucket = map[assoc];
|
126
|
+
parts.push(#{`bucket[0]`.to_json} + ': ' + #{`bucket[1]`.to_json});
|
127
|
+
}
|
128
|
+
|
129
|
+
return '{' + parts.join(', ') + '}';
|
130
|
+
}
|
131
|
+
end
|
132
|
+
end
|
data/spec/parse_spec.rb
ADDED
@@ -0,0 +1,31 @@
|
|
1
|
+
describe "JSON.parse" do
|
2
|
+
it "parses null into nil" do
|
3
|
+
JSON.parse("null").should be_nil
|
4
|
+
end
|
5
|
+
|
6
|
+
it "parses true into true" do
|
7
|
+
JSON.parse("true").should be_true
|
8
|
+
end
|
9
|
+
|
10
|
+
it "parses false into false" do
|
11
|
+
JSON.parse("false").should be_false
|
12
|
+
end
|
13
|
+
|
14
|
+
it "parses numbers into numbers" do
|
15
|
+
JSON.parse("42").should == 42
|
16
|
+
JSON.parse("3.142").should == 3.142
|
17
|
+
end
|
18
|
+
|
19
|
+
it "parses arrays into ruby arrays" do
|
20
|
+
JSON.parse("[]").should == []
|
21
|
+
JSON.parse("[1, 2, 3]").should == [1, 2, 3]
|
22
|
+
JSON.parse("[[1, 2, 3], [4, 5]]").should == [[1, 2, 3], [4, 5]]
|
23
|
+
JSON.parse("[null, true, false]").should == [nil, true, false]
|
24
|
+
end
|
25
|
+
|
26
|
+
it "parses object literals into ruby hashes" do
|
27
|
+
JSON.parse("{}").should == {}
|
28
|
+
JSON.parse('{"a": "b"}').should == {"a" => "b"}
|
29
|
+
JSON.parse('{"a": null, "b": 10, "c": [true, false]}').should == {"a" => nil, "b" => 10, "c" => [true, false]}
|
30
|
+
end
|
31
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
describe "Numeric#to_json" do
|
2
|
+
it "returns a string representing the number" do
|
3
|
+
42.to_json.should == "42"
|
4
|
+
3.142.to_json.should == "3.142"
|
5
|
+
end
|
6
|
+
end
|
7
|
+
|
8
|
+
describe "String#to_json" do
|
9
|
+
it "returns an escaped string" do
|
10
|
+
"foo".to_json.should == "\"foo\""
|
11
|
+
"bar\nbaz".to_json.should == "\"bar\\nbaz\""
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
describe "NilClass#to_json" do
|
16
|
+
it "returns 'null'" do
|
17
|
+
nil.to_json.should == "null"
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Boolean#to_s" do
|
22
|
+
it "returns 'true' when true" do
|
23
|
+
true.to_json.should == "true"
|
24
|
+
end
|
25
|
+
|
26
|
+
it "returns 'false' when false" do
|
27
|
+
false.to_json.should == "false"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe "Kernel#to_json" do
|
32
|
+
it "returns an escaped #to_s of the receiver" do
|
33
|
+
self.to_json.should be_kind_of(String)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "Array#to_json" do
|
38
|
+
it "returns a string of all array elements converted to json" do
|
39
|
+
[].to_json.should == "[]"
|
40
|
+
[1, 2, 3].to_json.should == "[1, 2, 3]"
|
41
|
+
[true, nil, false, "3", 42].to_json.should == '[true, null, false, "3", 42]'
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
describe "Hash#to_json" do
|
46
|
+
it "returns a string of all key and value pairs" do
|
47
|
+
{}.to_json.should == "{}"
|
48
|
+
{"a" => 1, "b" => 2}.to_json.should == '{"a": 1, "b": 2}'
|
49
|
+
|
50
|
+
hash = {"a" => 1, "b" => false, "c" => nil, "d" => true}
|
51
|
+
JSON.parse(hash.to_json).should == hash
|
52
|
+
end
|
53
|
+
end
|
metadata
ADDED
@@ -0,0 +1,51 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: opal-json
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Adam Beynon
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-05-20 00:00:00.000000000Z
|
13
|
+
dependencies: []
|
14
|
+
description:
|
15
|
+
email:
|
16
|
+
- adam@adambeynon.com
|
17
|
+
executables: []
|
18
|
+
extensions: []
|
19
|
+
extra_rdoc_files: []
|
20
|
+
files:
|
21
|
+
- lib/opal/json.rb
|
22
|
+
- README.md
|
23
|
+
- spec/parse_spec.rb
|
24
|
+
- spec/to_json_spec.rb
|
25
|
+
homepage: http://github.com/opal/opal_json
|
26
|
+
licenses: []
|
27
|
+
post_install_message:
|
28
|
+
rdoc_options: []
|
29
|
+
require_paths:
|
30
|
+
- lib
|
31
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
32
|
+
none: false
|
33
|
+
requirements:
|
34
|
+
- - ! '>='
|
35
|
+
- !ruby/object:Gem::Version
|
36
|
+
version: '0'
|
37
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
38
|
+
none: false
|
39
|
+
requirements:
|
40
|
+
- - ! '>='
|
41
|
+
- !ruby/object:Gem::Version
|
42
|
+
version: '0'
|
43
|
+
requirements: []
|
44
|
+
rubyforge_project:
|
45
|
+
rubygems_version: 1.8.11
|
46
|
+
signing_key:
|
47
|
+
specification_version: 3
|
48
|
+
summary: JSON implementation for opal
|
49
|
+
test_files:
|
50
|
+
- spec/parse_spec.rb
|
51
|
+
- spec/to_json_spec.rb
|