yagni_json_encoder 0.0.2 → 1.0.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/README.md +1 -1
- data/lib/activesupport/json_encoder.rb +13 -4
- data/lib/yagni_json_encoder.rb +13 -3
- data/test/decoding_test.rb +117 -0
- data/test/encoding_test.rb +1 -3
- metadata +8 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: fe7c535d50a8b685f002034847b2f24b7a7d6546
|
4
|
+
data.tar.gz: 2b27b43016e451fee668cfcffaf0ffc0ee84916b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f069f0c535e3b667eda181c617a43440d086d5c7582bbe8e9f13bc9c5461d040fae71e43f85ed06cb90afc53ddc42afea596143dfe9f26ca4d8418008bb97115
|
7
|
+
data.tar.gz: 8f13b2b270bc2b28208bbbea427c43fa251d52b4008572ed972b84a249f607a5c5d86188dcb7cd735fc7e28b4098897871efe367a8041ecf2d39930c05f85347
|
data/README.md
CHANGED
@@ -27,7 +27,7 @@ the heavy JSON encoding work.
|
|
27
27
|
|
28
28
|
In a real Rails app, I benchmarked `Tips.all.to_json` with the different
|
29
29
|
encoders. On average, YagniJsonEncoder is ~2x as fast. However, you could
|
30
|
-
see bigger gains if
|
30
|
+
see bigger gains if your models are text/string-heavy.
|
31
31
|
|
32
32
|
```
|
33
33
|
Calculating -------------------------------------
|
@@ -1,10 +1,19 @@
|
|
1
|
-
require 'yagni_json_encoder'
|
2
|
-
|
3
1
|
module ActiveSupport
|
4
2
|
self.json_encoder = YagniJsonEncoder
|
5
3
|
|
6
4
|
def self.escape_html_entities_in_json=(*_args)
|
7
|
-
|
8
|
-
|
5
|
+
raise StandardError,
|
6
|
+
'escape_html_entities_in_json is not supported in YagniJsonEncoder'
|
7
|
+
end
|
8
|
+
|
9
|
+
def self.parse_json_times
|
10
|
+
raise StandardError,
|
11
|
+
'ActiveSupport.parse_json_times not supported in YagniJsonEncoder'
|
12
|
+
end
|
13
|
+
|
14
|
+
module JSON
|
15
|
+
def self.decode(json)
|
16
|
+
YagniJsonEncoder::JSON.parse(json, quirks_mode: true)
|
17
|
+
end
|
9
18
|
end
|
10
19
|
end
|
data/lib/yagni_json_encoder.rb
CHANGED
@@ -1,6 +1,16 @@
|
|
1
|
+
begin
|
2
|
+
require 'json'
|
3
|
+
rescue StandardError
|
4
|
+
nil # ignore
|
5
|
+
end
|
6
|
+
|
7
|
+
require "active_support/json"
|
1
8
|
require 'oj'
|
2
9
|
|
3
10
|
class YagniJsonEncoder
|
11
|
+
Oj.default_options = { mode: :compat, after_sep: 0 }
|
12
|
+
JSON = Oj.mimic_JSON
|
13
|
+
|
4
14
|
attr_reader :options
|
5
15
|
|
6
16
|
def initialize(options = nil)
|
@@ -8,9 +18,9 @@ class YagniJsonEncoder
|
|
8
18
|
end
|
9
19
|
|
10
20
|
def encode(value)
|
11
|
-
|
12
|
-
|
13
|
-
|
21
|
+
JSON.generate value.as_json(options.dup),
|
22
|
+
quirks_mode: true,
|
23
|
+
max_nesting: false
|
14
24
|
end
|
15
25
|
end
|
16
26
|
|
@@ -0,0 +1,117 @@
|
|
1
|
+
require 'yagni_json_encoder'
|
2
|
+
require "test_helper"
|
3
|
+
require "active_support/time"
|
4
|
+
require "time_zone_test_helpers"
|
5
|
+
|
6
|
+
class TestJSONDecoding < ActiveSupport::TestCase
|
7
|
+
include TimeZoneTestHelpers
|
8
|
+
|
9
|
+
class Foo
|
10
|
+
def self.json_create(object)
|
11
|
+
"Foo"
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
TESTS = {
|
16
|
+
%q({"returnTo":{"\/categories":"\/"}}) => { "returnTo" => { "/categories" => "/" } },
|
17
|
+
%q({"return\\"To\\":":{"\/categories":"\/"}}) => { "return\"To\":" => { "/categories" => "/" } },
|
18
|
+
%q({"returnTo":{"\/categories":1}}) => { "returnTo" => { "/categories" => 1 } },
|
19
|
+
%({"returnTo":[1,"a"]}) => { "returnTo" => [1, "a"] },
|
20
|
+
%({"returnTo":[1,"\\"a\\",", "b"]}) => { "returnTo" => [1, "\"a\",", "b"] },
|
21
|
+
%({"a": "'", "b": "5,000"}) => { "a" => "'", "b" => "5,000" },
|
22
|
+
%({"a": "a's, b's and c's", "b": "5,000"}) => { "a" => "a's, b's and c's", "b" => "5,000" },
|
23
|
+
# multibyte
|
24
|
+
%({"matzue": "松江", "asakusa": "浅草"}) => { "matzue" => "松江", "asakusa" => "浅草" },
|
25
|
+
%({"a": "2007-01-01"}) => { "a" => Date.new(2007, 1, 1) },
|
26
|
+
%({"a": "2007-01-01 01:12:34 Z"}) => { "a" => Time.utc(2007, 1, 1, 1, 12, 34) },
|
27
|
+
%(["2007-01-01 01:12:34 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34)],
|
28
|
+
%(["2007-01-01 01:12:34 Z", "2007-01-01 01:12:35 Z"]) => [Time.utc(2007, 1, 1, 1, 12, 34), Time.utc(2007, 1, 1, 1, 12, 35)],
|
29
|
+
# no time zone
|
30
|
+
%({"a": "2007-01-01 01:12:34"}) => { "a" => Time.new(2007, 1, 1, 1, 12, 34, "-05:00") },
|
31
|
+
# invalid date
|
32
|
+
%({"a": "1089-10-40"}) => { "a" => "1089-10-40" },
|
33
|
+
# xmlschema date notation
|
34
|
+
%({"a": "2009-08-10T19:01:02"}) => { "a" => Time.new(2009, 8, 10, 19, 1, 2, "-04:00") },
|
35
|
+
%({"a": "2009-08-10T19:01:02Z"}) => { "a" => Time.utc(2009, 8, 10, 19, 1, 2) },
|
36
|
+
%({"a": "2009-08-10T19:01:02+02:00"}) => { "a" => Time.utc(2009, 8, 10, 17, 1, 2) },
|
37
|
+
%({"a": "2009-08-10T19:01:02-05:00"}) => { "a" => Time.utc(2009, 8, 11, 00, 1, 2) },
|
38
|
+
# needs to be *exact*
|
39
|
+
%({"a": " 2007-01-01 01:12:34 Z "}) => { "a" => " 2007-01-01 01:12:34 Z " },
|
40
|
+
%({"a": "2007-01-01 : it's your birthday"}) => { "a" => "2007-01-01 : it's your birthday" },
|
41
|
+
%([]) => [],
|
42
|
+
%({}) => {},
|
43
|
+
%({"a":1}) => { "a" => 1 },
|
44
|
+
%({"a": ""}) => { "a" => "" },
|
45
|
+
%({"a":"\\""}) => { "a" => "\"" },
|
46
|
+
%({"a": null}) => { "a" => nil },
|
47
|
+
%({"a": true}) => { "a" => true },
|
48
|
+
%({"a": false}) => { "a" => false },
|
49
|
+
'{"bad":"\\\\","trailing":""}' => { "bad" => "\\", "trailing" => "" },
|
50
|
+
%q({"a": "http:\/\/test.host\/posts\/1"}) => { "a" => "http://test.host/posts/1" },
|
51
|
+
%q({"a": "\u003cunicode\u0020escape\u003e"}) => { "a" => "<unicode escape>" },
|
52
|
+
'{"a": "\\\\u0020skip double backslashes"}' => { "a" => "\\u0020skip double backslashes" },
|
53
|
+
%q({"a": "\u003cbr /\u003e"}) => { "a" => "<br />" },
|
54
|
+
%q({"b":["\u003ci\u003e","\u003cb\u003e","\u003cu\u003e"]}) => { "b" => ["<i>", "<b>", "<u>"] },
|
55
|
+
# test combination of dates and escaped or unicode encoded data in arrays
|
56
|
+
%q([{"d":"1970-01-01", "s":"\u0020escape"},{"d":"1970-01-01", "s":"\u0020escape"}]) =>
|
57
|
+
[{ "d" => Date.new(1970, 1, 1), "s" => " escape" }, { "d" => Date.new(1970, 1, 1), "s" => " escape" }],
|
58
|
+
%q([{"d":"1970-01-01","s":"http:\/\/example.com"},{"d":"1970-01-01","s":"http:\/\/example.com"}]) =>
|
59
|
+
[{ "d" => Date.new(1970, 1, 1), "s" => "http://example.com" },
|
60
|
+
{ "d" => Date.new(1970, 1, 1), "s" => "http://example.com" }],
|
61
|
+
# tests escaping of "\n" char with Yaml backend
|
62
|
+
%q({"a":"\n"}) => { "a" => "\n" },
|
63
|
+
%q({"a":"\u000a"}) => { "a" => "\n" },
|
64
|
+
%q({"a":"Line1\u000aLine2"}) => { "a" => "Line1\nLine2" },
|
65
|
+
# prevent json unmarshalling
|
66
|
+
'{"json_class":"TestJSONDecoding::Foo"}' => { "json_class" => "TestJSONDecoding::Foo" },
|
67
|
+
# json "fragments" - these are invalid JSON, but ActionPack relies on this
|
68
|
+
'"a string"' => "a string",
|
69
|
+
"1.1" => 1.1,
|
70
|
+
"1" => 1,
|
71
|
+
"-1" => -1,
|
72
|
+
"true" => true,
|
73
|
+
"false" => false,
|
74
|
+
"null" => nil
|
75
|
+
}
|
76
|
+
|
77
|
+
TESTS.each_with_index do |(json, expected), index|
|
78
|
+
fail_message = "JSON decoding failed for #{json}"
|
79
|
+
|
80
|
+
test "json decodes #{index}" do
|
81
|
+
with_tz_default "Eastern Time (US & Canada)" do
|
82
|
+
with_parse_json_times(true) do
|
83
|
+
silence_warnings do
|
84
|
+
if expected.nil?
|
85
|
+
assert_nil ActiveSupport::JSON.decode(json), fail_message
|
86
|
+
else
|
87
|
+
assert_equal expected, ActiveSupport::JSON.decode(json), fail_message
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
test "json decodes time json with time parsing disabled" do
|
96
|
+
with_parse_json_times(false) do
|
97
|
+
expected = { "a" => "2007-01-01 01:12:34 Z" }
|
98
|
+
assert_equal expected, ActiveSupport::JSON.decode(%({"a": "2007-01-01 01:12:34 Z"}))
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def test_failed_json_decoding
|
103
|
+
assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%(undefined)) }
|
104
|
+
assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({a: 1})) }
|
105
|
+
assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%({: 1})) }
|
106
|
+
# assert_raise(ActiveSupport::JSON.parse_error) { ActiveSupport::JSON.decode(%()) }
|
107
|
+
end
|
108
|
+
|
109
|
+
def test_cannot_pass_unsupported_options
|
110
|
+
assert_raise(ArgumentError) { ActiveSupport::JSON.decode("", create_additions: true) }
|
111
|
+
end
|
112
|
+
|
113
|
+
private
|
114
|
+
|
115
|
+
def with_parse_json_times(value)
|
116
|
+
end
|
117
|
+
end
|
data/test/encoding_test.rb
CHANGED
@@ -1,12 +1,10 @@
|
|
1
|
-
require '
|
1
|
+
require 'yagni_json_encoder'
|
2
2
|
require 'active_support/time'
|
3
3
|
require 'encoding_test_cases'
|
4
4
|
require 'securerandom'
|
5
5
|
require 'test_helper'
|
6
6
|
require 'time_zone_test_helpers'
|
7
7
|
|
8
|
-
require 'yagni_json_encoder'
|
9
|
-
|
10
8
|
class TestJSONEncoding < ActiveSupport::TestCase
|
11
9
|
include TimeZoneTestHelpers
|
12
10
|
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: yagni_json_encoder
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ian Ker-Seymer
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2017-04-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rake
|
@@ -30,14 +30,14 @@ dependencies:
|
|
30
30
|
requirements:
|
31
31
|
- - "~>"
|
32
32
|
- !ruby/object:Gem::Version
|
33
|
-
version:
|
33
|
+
version: 2.18.5
|
34
34
|
type: :runtime
|
35
35
|
prerelease: false
|
36
36
|
version_requirements: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
|
-
version:
|
40
|
+
version: 2.18.5
|
41
41
|
- !ruby/object:Gem::Dependency
|
42
42
|
name: activesupport
|
43
43
|
requirement: !ruby/object:Gem::Requirement
|
@@ -63,6 +63,7 @@ files:
|
|
63
63
|
- README.md
|
64
64
|
- lib/activesupport/json_encoder.rb
|
65
65
|
- lib/yagni_json_encoder.rb
|
66
|
+
- test/decoding_test.rb
|
66
67
|
- test/encoding_test.rb
|
67
68
|
- test/encoding_test_cases.rb
|
68
69
|
- test/test_helper.rb
|
@@ -87,13 +88,13 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
87
88
|
version: '0'
|
88
89
|
requirements: []
|
89
90
|
rubyforge_project:
|
90
|
-
rubygems_version: 2.
|
91
|
+
rubygems_version: 2.5.2
|
91
92
|
signing_key:
|
92
93
|
specification_version: 4
|
93
94
|
summary: "~2x faster JSON encoder for Rails"
|
94
95
|
test_files:
|
95
|
-
- test/time_zone_test_helpers.rb
|
96
96
|
- test/encoding_test_cases.rb
|
97
97
|
- test/test_helper.rb
|
98
|
+
- test/time_zone_test_helpers.rb
|
99
|
+
- test/decoding_test.rb
|
98
100
|
- test/encoding_test.rb
|
99
|
-
has_rdoc:
|