ruby-jq 0.1.9 → 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.
- checksums.yaml +4 -4
- data/.rubocop.yml +14 -0
- data/.travis.yml +3 -0
- data/Gemfile +2 -0
- data/README.md +4 -1
- data/Rakefile +10 -2
- data/ext/extconf.rb +11 -9
- data/ext/jq_core.c +30 -2
- data/ext/jq_core.h +1 -0
- data/lib/jq.rb +3 -1
- data/lib/jq/extend.rb +8 -4
- data/lib/jq/parser.rb +54 -46
- data/lib/jq/version.rb +3 -1
- data/ruby-jq.gemspec +21 -19
- data/spec/jq_spec.rb +183 -174
- data/spec/spec_helper.rb +3 -1
- metadata +17 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 05ca27e78db064b6859a2708c228ca789731dbdd8f1c90fd1975f5bfdff3c2ab
|
4
|
+
data.tar.gz: 2f35f8b1f0d98b62c895f6033e6ae8756d8e54e39dd9bc092e4ae7f0848d8c80
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: f5c138883fec3bd9c3b76b974b54f38c1e111c0f9b875b625d16bd171c90812f02caff1ddf5b155b649086fae1c4eac20dd895713434e9d502f4ac74158df32d
|
7
|
+
data.tar.gz: 7e757bd1b61761aa12ca923a342c39cf74e824e4abd872ee463d7589a5bd16e95c7e127590d68d7d9fb29ad16c66bd73365de64e718e8f0205745b2565acbd9b
|
data/.rubocop.yml
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
AllCops:
|
2
|
+
Exclude:
|
3
|
+
- 'tmp/**/*'
|
4
|
+
TargetRubyVersion: 2.3
|
5
|
+
Metrics/LineLength:
|
6
|
+
Enabled: false
|
7
|
+
Metrics/BlockLength:
|
8
|
+
Enabled: false
|
9
|
+
Style/Documentation:
|
10
|
+
Enabled: false
|
11
|
+
Metrics/AbcSize:
|
12
|
+
Enabled: false
|
13
|
+
Metrics/MethodLength:
|
14
|
+
Enabled: false
|
data/.travis.yml
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -59,7 +59,10 @@ jq.search('.[]') do |value|
|
|
59
59
|
# => [1, "2", 3]
|
60
60
|
end
|
61
61
|
|
62
|
-
jq
|
62
|
+
p jq.search('.[]')
|
63
|
+
# => ["FOO", {"BAR"=>[100, 200]}, 1.23, [1, "2", 3]]
|
64
|
+
|
65
|
+
jq = JQ(src, parse_json: false)
|
63
66
|
|
64
67
|
jq.search('.[1].BAR') do |value|
|
65
68
|
p value
|
data/Rakefile
CHANGED
@@ -1,10 +1,18 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'bundler/gem_tasks'
|
2
4
|
require 'rspec/core/rake_task'
|
3
5
|
require 'rake/extensiontask'
|
6
|
+
require 'rubocop/rake_task'
|
4
7
|
|
5
8
|
RSpec::Core::RakeTask.new('spec')
|
9
|
+
|
6
10
|
Rake::ExtensionTask.new('jq_core') do |ext|
|
7
11
|
ext.ext_dir = 'ext'
|
8
12
|
end
|
9
13
|
|
10
|
-
|
14
|
+
RuboCop::RakeTask.new do |task|
|
15
|
+
task.options = %w[-c .rubocop.yml]
|
16
|
+
end
|
17
|
+
|
18
|
+
task default: %i[compile rubocop spec]
|
data/ext/extconf.rb
CHANGED
@@ -1,7 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'mkmf'
|
2
4
|
|
3
5
|
def using_system_libraries?
|
4
|
-
arg_config('--use-system-libraries',
|
6
|
+
arg_config('--use-system-libraries', ENV.key?('RUBYJQ_USE_SYSTEM_LIBRARIES'))
|
5
7
|
end
|
6
8
|
|
7
9
|
unless using_system_libraries?
|
@@ -10,24 +12,24 @@ unless using_system_libraries?
|
|
10
12
|
require 'rubygems'
|
11
13
|
require 'mini_portile2'
|
12
14
|
|
13
|
-
recipe = MiniPortile.new(
|
14
|
-
recipe.files = [
|
15
|
+
recipe = MiniPortile.new('jq', '1.6')
|
16
|
+
recipe.files = ['https://github.com/stedolan/jq/archive/jq-1.6.tar.gz']
|
15
17
|
recipe.configure_options = [
|
16
|
-
|
17
|
-
|
18
|
+
'--enable-shared',
|
19
|
+
'--disable-maintainer-mode'
|
18
20
|
]
|
19
21
|
class << recipe
|
20
22
|
def configure
|
21
|
-
execute(
|
23
|
+
execute('autoreconf', 'autoreconf -i')
|
22
24
|
super
|
23
25
|
end
|
24
26
|
end
|
25
27
|
recipe.cook
|
26
28
|
recipe.activate
|
27
|
-
$LIBPATH = ["#{recipe.path}/lib"] | $LIBPATH
|
28
|
-
$CPPFLAGS << " -I#{recipe.path}/include"
|
29
|
+
$LIBPATH = ["#{recipe.path}/lib"] | $LIBPATH # rubocop:disable Style/GlobalVars
|
30
|
+
$CPPFLAGS << " -I#{recipe.path}/include" # rubocop:disable Style/GlobalVars
|
29
31
|
end
|
30
32
|
|
31
|
-
abort
|
33
|
+
abort 'libjq not found' unless have_library('jq')
|
32
34
|
|
33
35
|
create_makefile('jq_core')
|
data/ext/jq_core.c
CHANGED
@@ -2,6 +2,24 @@
|
|
2
2
|
|
3
3
|
static VALUE rb_eJQ_Error;
|
4
4
|
|
5
|
+
static void jq_err_cb(void *data, jv msg) {
|
6
|
+
VALUE errmsg;
|
7
|
+
struct jq_container *p = (struct jq_container *) data;
|
8
|
+
msg = jq_format_error(msg);
|
9
|
+
|
10
|
+
errmsg = rb_str_new2(jv_string_value(msg));
|
11
|
+
|
12
|
+
if (NIL_P(p->errmsg)) {
|
13
|
+
p->errmsg = errmsg;
|
14
|
+
} else {
|
15
|
+
rb_str_concat(errmsg, rb_str_new2("\n"));
|
16
|
+
rb_str_concat(errmsg, p->errmsg);
|
17
|
+
p->errmsg = errmsg;
|
18
|
+
}
|
19
|
+
|
20
|
+
jv_free(msg);
|
21
|
+
}
|
22
|
+
|
5
23
|
static void rb_jq_free(struct jq_container *p) {
|
6
24
|
xfree(p);
|
7
25
|
}
|
@@ -12,6 +30,7 @@ static VALUE rb_jq_alloc(VALUE klass) {
|
|
12
30
|
p->jq = NULL;
|
13
31
|
p->parser = NULL;
|
14
32
|
p->closed = 1;
|
33
|
+
p->errmsg = Qnil;
|
15
34
|
return Data_Wrap_Struct(klass, 0, rb_jq_free, p);
|
16
35
|
}
|
17
36
|
|
@@ -28,16 +47,24 @@ static VALUE rb_jq_initialize(VALUE self, VALUE program) {
|
|
28
47
|
rb_raise(rb_eJQ_Error, "%s", strerror(errno));
|
29
48
|
}
|
30
49
|
|
50
|
+
jq_set_error_cb(jq, jq_err_cb, p);
|
51
|
+
|
31
52
|
compiled = jq_compile(jq, RSTRING_PTR(program));
|
32
53
|
|
33
54
|
if (!compiled) {
|
34
55
|
jq_teardown(&jq);
|
35
|
-
|
56
|
+
|
57
|
+
if (NIL_P(p->errmsg)) {
|
58
|
+
rb_raise(rb_eJQ_Error, "compile error");
|
59
|
+
} else {
|
60
|
+
rb_raise(rb_eJQ_Error, "%s", RSTRING_PTR(p->errmsg));
|
61
|
+
}
|
36
62
|
}
|
37
63
|
|
38
64
|
p->jq = jq;
|
39
65
|
p->parser = NULL;
|
40
66
|
p->closed = 0;
|
67
|
+
p->errmsg = Qnil;
|
41
68
|
|
42
69
|
return Qnil;
|
43
70
|
}
|
@@ -51,14 +78,15 @@ static VALUE rb_jq_close(VALUE self) {
|
|
51
78
|
p->jq = NULL;
|
52
79
|
p->parser = NULL;
|
53
80
|
p->closed = 1;
|
81
|
+
p->errmsg = Qnil;
|
54
82
|
}
|
55
83
|
|
56
84
|
return Qnil;
|
57
85
|
}
|
58
86
|
|
59
87
|
static void jq_process(jq_state *jq, jv value, VALUE (*proc)(), int *status, VALUE *errmsg) {
|
60
|
-
jq_start(jq, value, 0);
|
61
88
|
jv result;
|
89
|
+
jq_start(jq, value, 0);
|
62
90
|
|
63
91
|
while (jv_is_valid(result = jq_next(jq))) {
|
64
92
|
jv dumped = jv_dump_string(result, 0);
|
data/ext/jq_core.h
CHANGED
data/lib/jq.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'multi_json'
|
2
4
|
require 'tempfile'
|
3
5
|
require 'stringio'
|
@@ -6,6 +8,6 @@ require 'jq_core'
|
|
6
8
|
require 'jq/version'
|
7
9
|
require 'jq/parser'
|
8
10
|
|
9
|
-
def JQ(src, options = {})
|
11
|
+
def JQ(src, options = {}) # rubocop:disable Naming/MethodName
|
10
12
|
JQ::Parser.new(src, options)
|
11
13
|
end
|
data/lib/jq/extend.rb
CHANGED
@@ -1,9 +1,13 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require 'jq'
|
2
4
|
|
3
|
-
module JQ
|
4
|
-
|
5
|
-
|
6
|
-
|
5
|
+
module JQ
|
6
|
+
module Extend
|
7
|
+
def jq(program, &block)
|
8
|
+
src = MultiJson.dump(self)
|
9
|
+
JQ(src).search(program, &block)
|
10
|
+
end
|
7
11
|
end
|
8
12
|
end
|
9
13
|
|
data/lib/jq/parser.rb
CHANGED
@@ -1,65 +1,73 @@
|
|
1
|
-
|
2
|
-
BUFSIZ = 4096
|
1
|
+
# frozen_string_literal: true
|
3
2
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
:parse_json => true,
|
8
|
-
}.merge(options)
|
9
|
-
end
|
3
|
+
module JQ
|
4
|
+
class Parser
|
5
|
+
BUFSIZ = 4096
|
10
6
|
|
11
|
-
|
12
|
-
|
13
|
-
|
7
|
+
def initialize(src, options = {})
|
8
|
+
@src = kind_of_io?(src) ? src : src.to_s
|
9
|
+
@options = {
|
10
|
+
parse_json: true
|
11
|
+
}.merge(options)
|
12
|
+
end
|
14
13
|
|
15
|
-
|
16
|
-
|
14
|
+
def search(program, &block)
|
15
|
+
@src.rewind if kind_of_io?(@src)
|
16
|
+
retval = nil
|
17
17
|
|
18
|
-
block
|
19
|
-
block_orig
|
20
|
-
end
|
21
|
-
else
|
22
|
-
retval = []
|
18
|
+
if block
|
19
|
+
block_orig = block
|
23
20
|
|
24
|
-
|
25
|
-
|
21
|
+
block = proc do |str|
|
22
|
+
block_orig.call(parse_json(str))
|
23
|
+
end
|
24
|
+
else
|
25
|
+
retval = []
|
26
|
+
|
27
|
+
block = proc do |str|
|
28
|
+
retval << parse_json(str)
|
29
|
+
end
|
26
30
|
end
|
27
|
-
end
|
28
31
|
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
32
|
+
jq(program) do |jq_core|
|
33
|
+
if kind_of_io?(@src)
|
34
|
+
while (buf = @src.read(BUFSIZ))
|
35
|
+
jq_core.update(buf, !@src.eof?, &block)
|
36
|
+
end
|
37
|
+
else
|
38
|
+
jq_core.update(@src, false, &block)
|
33
39
|
end
|
34
|
-
else
|
35
|
-
jq_core.update(@src, false, &block)
|
36
40
|
end
|
41
|
+
|
42
|
+
retval
|
37
43
|
end
|
38
44
|
|
39
|
-
|
40
|
-
end
|
45
|
+
private
|
41
46
|
|
42
|
-
|
43
|
-
|
44
|
-
|
47
|
+
def jq(program)
|
48
|
+
jq_core = nil
|
49
|
+
retval = nil
|
45
50
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
+
begin
|
52
|
+
jq_core = JQ::Core.new(program)
|
53
|
+
retval = yield(jq_core)
|
54
|
+
ensure
|
55
|
+
jq_core&.close
|
56
|
+
end
|
57
|
+
|
58
|
+
retval
|
51
59
|
end
|
52
|
-
end
|
53
60
|
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
61
|
+
def parse_json(str)
|
62
|
+
if @options[:parse_json]
|
63
|
+
MultiJson.load("[#{str}]").first
|
64
|
+
else
|
65
|
+
str
|
66
|
+
end
|
59
67
|
end
|
60
|
-
end
|
61
68
|
|
62
|
-
|
63
|
-
|
69
|
+
def kind_of_io?(obj)
|
70
|
+
[IO, Tempfile, StringIO].any? { |c| obj.is_a?(c) }
|
71
|
+
end
|
64
72
|
end
|
65
73
|
end
|
data/lib/jq/version.rb
CHANGED
data/ruby-jq.gemspec
CHANGED
@@ -1,28 +1,30 @@
|
|
1
|
-
#
|
2
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
lib = File.expand_path('lib', __dir__)
|
3
4
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
5
|
require 'jq/version'
|
5
6
|
|
6
7
|
Gem::Specification.new do |spec|
|
7
|
-
spec.name =
|
8
|
+
spec.name = 'ruby-jq'
|
8
9
|
spec.version = JQ::VERSION
|
9
|
-
spec.author =
|
10
|
-
spec.email =
|
11
|
-
spec.description =
|
12
|
-
spec.summary =
|
13
|
-
spec.homepage =
|
14
|
-
spec.license =
|
10
|
+
spec.author = 'winebarrel'
|
11
|
+
spec.email = 'sgwr_dts@yahoo.co.jp'
|
12
|
+
spec.description = 'Ruby bindings for jq'
|
13
|
+
spec.summary = 'Ruby bindings for jq'
|
14
|
+
spec.homepage = 'https://github.com/winebarrel/ruby-jq'
|
15
|
+
spec.license = 'MIT'
|
15
16
|
|
16
|
-
spec.files = `git ls-files`.split(
|
17
|
-
spec.extensions =
|
18
|
-
#spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
19
|
-
#spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
|
-
spec.require_paths = [
|
17
|
+
spec.files = `git ls-files`.split($INPUT_RECORD_SEPARATOR)
|
18
|
+
spec.extensions = 'ext/extconf.rb'
|
19
|
+
# spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
20
|
+
# spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
21
|
+
spec.require_paths = ['lib']
|
21
22
|
|
22
|
-
spec.add_dependency
|
23
|
-
spec.add_runtime_dependency
|
23
|
+
spec.add_dependency 'multi_json'
|
24
|
+
spec.add_runtime_dependency 'mini_portile2', '>= 2.2.0'
|
24
25
|
|
25
|
-
spec.add_development_dependency
|
26
|
-
spec.add_development_dependency
|
27
|
-
spec.add_development_dependency
|
26
|
+
spec.add_development_dependency 'rake'
|
27
|
+
spec.add_development_dependency 'rake-compiler'
|
28
|
+
spec.add_development_dependency 'rspec'
|
29
|
+
spec.add_development_dependency 'rubocop'
|
28
30
|
end
|
data/spec/jq_spec.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
describe JQ do
|
2
4
|
specify 'int' do
|
3
5
|
expect(JQ('1').search('.')).to eq([1])
|
@@ -16,72 +18,73 @@ describe JQ do
|
|
16
18
|
end
|
17
19
|
|
18
20
|
specify 'string' do
|
19
|
-
expect(JQ('"Zzz"').search('.')).to eq([
|
21
|
+
expect(JQ('"Zzz"').search('.')).to eq(['Zzz'])
|
20
22
|
|
21
23
|
JQ('"Zzz"').search('.') do |value|
|
22
|
-
expect(value).to eq(
|
24
|
+
expect(value).to eq('Zzz')
|
23
25
|
end
|
24
26
|
end
|
25
27
|
|
26
28
|
specify 'array' do
|
27
|
-
expect(JQ('[1, "2", 3]').search('.')).to eq([[1,
|
29
|
+
expect(JQ('[1, "2", 3]').search('.')).to eq([[1, '2', 3]])
|
28
30
|
|
29
31
|
JQ('[1, "2", 3]').search('.') do |value|
|
30
|
-
expect(value).to eq([1,
|
32
|
+
expect(value).to eq([1, '2', 3])
|
31
33
|
end
|
32
34
|
end
|
33
35
|
|
34
36
|
specify 'hash' do
|
35
|
-
expect(JQ('{"foo":100, "bar":"zoo"}').search('.')).to eq([{
|
37
|
+
expect(JQ('{"foo":100, "bar":"zoo"}').search('.')).to eq([{ 'foo' => 100, 'bar' => 'zoo' }])
|
36
38
|
|
37
39
|
JQ('{"foo":100, "bar":"zoo"}').search('.') do |value|
|
38
|
-
expect(value).to eq(
|
40
|
+
expect(value).to eq('foo' => 100, 'bar' => 'zoo')
|
39
41
|
end
|
40
42
|
end
|
41
43
|
|
42
44
|
specify 'composition' do
|
43
|
-
src =
|
44
|
-
{
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
}
|
66
|
-
|
45
|
+
src = <<~JSON
|
46
|
+
{
|
47
|
+
"glossary": {
|
48
|
+
"title": "example glossary",
|
49
|
+
"GlossDiv": {
|
50
|
+
"title": "S",
|
51
|
+
"GlossList": {
|
52
|
+
"GlossEntry": {
|
53
|
+
"ID": "SGML",
|
54
|
+
"SortAs": "SGML",
|
55
|
+
"GlossTerm": "Standard Generalized Markup Language",
|
56
|
+
"Acronym": "SGML",
|
57
|
+
"Abbrev": "ISO 8879:1986",
|
58
|
+
"GlossDef": {
|
59
|
+
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
60
|
+
"GlossSeeAlso": ["GML", "XML"]
|
61
|
+
},
|
62
|
+
"GlossSee": "markup"
|
63
|
+
}
|
64
|
+
}
|
65
|
+
}
|
66
|
+
}
|
67
|
+
}
|
68
|
+
JSON
|
67
69
|
|
68
70
|
expected = {
|
69
|
-
|
70
|
-
{
|
71
|
-
{
|
72
|
-
{
|
73
|
-
{
|
74
|
-
|
75
|
-
{
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
71
|
+
'glossary' =>
|
72
|
+
{ 'GlossDiv' =>
|
73
|
+
{ 'GlossList' =>
|
74
|
+
{ 'GlossEntry' =>
|
75
|
+
{ 'GlossSee' => 'markup',
|
76
|
+
'GlossDef' =>
|
77
|
+
{ 'GlossSeeAlso' => %w[GML XML],
|
78
|
+
'para' =>
|
79
|
+
'A meta-markup language, used to create markup languages such as DocBook.' },
|
80
|
+
'Abbrev' => 'ISO 8879:1986',
|
81
|
+
'Acronym' => 'SGML',
|
82
|
+
'GlossTerm' => 'Standard Generalized Markup Language',
|
83
|
+
'SortAs' => 'SGML',
|
84
|
+
'ID' => 'SGML' } },
|
85
|
+
'title' => 'S' },
|
86
|
+
'title' => 'example glossary' }
|
87
|
+
}
|
85
88
|
|
86
89
|
expect(JQ(src).search('.')).to eq([expected])
|
87
90
|
|
@@ -91,49 +94,50 @@ describe JQ do
|
|
91
94
|
end
|
92
95
|
|
93
96
|
specify 'read from file' do
|
94
|
-
Tempfile.open("ruby-jq.spec.#{
|
95
|
-
src.puts(
|
96
|
-
{
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
97
|
+
Tempfile.open("ruby-jq.spec.#{$PROCESS_ID}") do |src|
|
98
|
+
src.puts(<<~JSON)
|
99
|
+
{
|
100
|
+
"glossary": {
|
101
|
+
"title": "example glossary",
|
102
|
+
"GlossDiv": {
|
103
|
+
"title": "S",
|
104
|
+
"GlossList": {
|
105
|
+
"GlossEntry": {
|
106
|
+
"ID": "SGML",
|
107
|
+
"SortAs": "SGML",
|
108
|
+
"GlossTerm": "Standard Generalized Markup Language",
|
109
|
+
"Acronym": "SGML",
|
110
|
+
"Abbrev": "ISO 8879:1986",
|
111
|
+
"GlossDef": {
|
112
|
+
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
113
|
+
"GlossSeeAlso": ["GML", "XML"]
|
114
|
+
},
|
115
|
+
"GlossSee": "markup"
|
116
|
+
}
|
117
|
+
}
|
113
118
|
}
|
114
119
|
}
|
115
120
|
}
|
116
|
-
|
117
|
-
}
|
118
|
-
EOS
|
121
|
+
JSON
|
119
122
|
|
120
123
|
expected = {
|
121
|
-
|
122
|
-
{
|
123
|
-
{
|
124
|
-
{
|
125
|
-
{
|
126
|
-
|
127
|
-
{
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
124
|
+
'glossary' =>
|
125
|
+
{ 'GlossDiv' =>
|
126
|
+
{ 'GlossList' =>
|
127
|
+
{ 'GlossEntry' =>
|
128
|
+
{ 'GlossSee' => 'markup',
|
129
|
+
'GlossDef' =>
|
130
|
+
{ 'GlossSeeAlso' => %w[GML XML],
|
131
|
+
'para' =>
|
132
|
+
'A meta-markup language, used to create markup languages such as DocBook.' },
|
133
|
+
'Abbrev' => 'ISO 8879:1986',
|
134
|
+
'Acronym' => 'SGML',
|
135
|
+
'GlossTerm' => 'Standard Generalized Markup Language',
|
136
|
+
'SortAs' => 'SGML',
|
137
|
+
'ID' => 'SGML' } },
|
138
|
+
'title' => 'S' },
|
139
|
+
'title' => 'example glossary' }
|
140
|
+
}
|
137
141
|
|
138
142
|
expect(JQ(src).search('.')).to eq([expected])
|
139
143
|
|
@@ -144,50 +148,51 @@ describe JQ do
|
|
144
148
|
end
|
145
149
|
|
146
150
|
specify 'read from file (> 4096)' do
|
147
|
-
Tempfile.open("ruby-jq.spec.#{
|
148
|
-
src.puts('[' + (1..10).map {
|
149
|
-
{
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
|
165
|
-
|
151
|
+
Tempfile.open("ruby-jq.spec.#{$PROCESS_ID}") do |src|
|
152
|
+
src.puts('[' + (1..10).map { <<~JSON }.join(',') + ']')
|
153
|
+
{
|
154
|
+
"glossary": {
|
155
|
+
"title": "example glossary",
|
156
|
+
"GlossDiv": {
|
157
|
+
"title": "S",
|
158
|
+
"GlossList": {
|
159
|
+
"GlossEntry": {
|
160
|
+
"ID": "SGML",
|
161
|
+
"SortAs": "SGML",
|
162
|
+
"GlossTerm": "Standard Generalized Markup Language",
|
163
|
+
"Acronym": "SGML",
|
164
|
+
"Abbrev": "ISO 8879:1986",
|
165
|
+
"GlossDef": {
|
166
|
+
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
167
|
+
"GlossSeeAlso": ["GML", "XML"]
|
168
|
+
},
|
169
|
+
"GlossSee": "markup"
|
170
|
+
}
|
171
|
+
}
|
166
172
|
}
|
167
173
|
}
|
168
174
|
}
|
169
|
-
|
170
|
-
}
|
171
|
-
EOS
|
175
|
+
JSON
|
172
176
|
|
173
177
|
expected = (1..10).map do
|
174
178
|
{
|
175
|
-
|
176
|
-
{
|
177
|
-
{
|
178
|
-
{
|
179
|
-
{
|
180
|
-
|
181
|
-
{
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
179
|
+
'glossary' =>
|
180
|
+
{ 'GlossDiv' =>
|
181
|
+
{ 'GlossList' =>
|
182
|
+
{ 'GlossEntry' =>
|
183
|
+
{ 'GlossSee' => 'markup',
|
184
|
+
'GlossDef' =>
|
185
|
+
{ 'GlossSeeAlso' => %w[GML XML],
|
186
|
+
'para' =>
|
187
|
+
'A meta-markup language, used to create markup languages such as DocBook.' },
|
188
|
+
'Abbrev' => 'ISO 8879:1986',
|
189
|
+
'Acronym' => 'SGML',
|
190
|
+
'GlossTerm' => 'Standard Generalized Markup Language',
|
191
|
+
'SortAs' => 'SGML',
|
192
|
+
'ID' => 'SGML' } },
|
193
|
+
'title' => 'S' },
|
194
|
+
'title' => 'example glossary' }
|
195
|
+
}
|
191
196
|
end
|
192
197
|
|
193
198
|
expect(JQ(src).search('.')).to eq([expected])
|
@@ -199,86 +204,90 @@ describe JQ do
|
|
199
204
|
end
|
200
205
|
|
201
206
|
specify 'parse_json => false' do
|
202
|
-
src =
|
203
|
-
{
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
223
|
-
|
224
|
-
}
|
225
|
-
|
207
|
+
src = <<~JSON
|
208
|
+
{
|
209
|
+
"glossary": {
|
210
|
+
"title": "example glossary",
|
211
|
+
"GlossDiv": {
|
212
|
+
"title": "S",
|
213
|
+
"GlossList": {
|
214
|
+
"GlossEntry": {
|
215
|
+
"ID": "SGML",
|
216
|
+
"SortAs": "SGML",
|
217
|
+
"GlossTerm": "Standard Generalized Markup Language",
|
218
|
+
"Acronym": "SGML",
|
219
|
+
"Abbrev": "ISO 8879:1986",
|
220
|
+
"GlossDef": {
|
221
|
+
"para": "A meta-markup language, used to create markup languages such as DocBook.",
|
222
|
+
"GlossSeeAlso": ["GML", "XML"]
|
223
|
+
},
|
224
|
+
"GlossSee": "markup"
|
225
|
+
}
|
226
|
+
}
|
227
|
+
}
|
228
|
+
}
|
229
|
+
}
|
230
|
+
JSON
|
226
231
|
|
227
232
|
expected = '{"glossary":{"GlossDiv":{"GlossList":{"GlossEntry":{"GlossSee":"markup","GlossDef":{"GlossSeeAlso":["GML","XML"],"para":"A meta-markup language, used to create markup languages such as DocBook."},"Abbrev":"ISO 8879:1986","Acronym":"SGML","GlossTerm":"Standard Generalized Markup Language","SortAs":"SGML","ID":"SGML"}},"title":"S"},"title":"example glossary"}}'
|
228
|
-
searched = JQ(src, :
|
233
|
+
searched = JQ(src, parse_json: false).search('.')
|
229
234
|
|
230
235
|
expect(searched.length).to eq(1)
|
231
236
|
expect(searched[0]).to be_kind_of(String)
|
232
237
|
expect(MultiJson.load(searched[0])).to eq(MultiJson.load(expected))
|
233
238
|
|
234
|
-
JQ(src, :
|
239
|
+
JQ(src, parse_json: false).search('.') do |value|
|
235
240
|
expect(value).to be_kind_of(String)
|
236
241
|
expect(MultiJson.load(value)).to eq(MultiJson.load(expected))
|
237
242
|
end
|
238
243
|
end
|
239
244
|
|
240
245
|
specify 'each value' do
|
241
|
-
src =
|
242
|
-
{"menu": {
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
}}
|
253
|
-
|
254
|
-
|
255
|
-
expect(JQ(src).search('.menu.popup.menuitem[].value')).to eq([
|
246
|
+
src = <<~JSON
|
247
|
+
{"menu": {
|
248
|
+
"id": "file",
|
249
|
+
"value": "File",
|
250
|
+
"popup": {
|
251
|
+
"menuitem": [
|
252
|
+
{"value": "New", "onclick": "CreateNewDoc()"},
|
253
|
+
{"value": "Open", "onclick": "OpenDoc()"},
|
254
|
+
{"value": "Close", "onclick": "CloseDoc()"}
|
255
|
+
]
|
256
|
+
}
|
257
|
+
}}
|
258
|
+
JSON
|
259
|
+
|
260
|
+
expect(JQ(src).search('.menu.popup.menuitem[].value')).to eq(%w[New Open Close])
|
256
261
|
end
|
257
262
|
|
258
263
|
specify 'compile error' do
|
259
|
-
expect
|
264
|
+
expect do
|
260
265
|
JQ('{}').search('...')
|
261
|
-
|
266
|
+
end.to raise_error(JQ::Error).with_message(<<~ERRMSG.chomp)
|
267
|
+
jq: 1 compile error
|
268
|
+
jq: error: Invalid numeric literal at EOF at line 1, column 3 (while parsing '...') at <top-level>, line 1:
|
269
|
+
...
|
270
|
+
ERRMSG
|
262
271
|
end
|
263
272
|
|
264
273
|
specify 'runtime error' do
|
265
|
-
expect
|
266
|
-
JQ('{}').search('.') do |
|
274
|
+
expect do
|
275
|
+
JQ('{}').search('.') do |_value|
|
267
276
|
raise 'runtime error'
|
268
277
|
end
|
269
|
-
|
278
|
+
end.to raise_error(RuntimeError)
|
270
279
|
end
|
271
280
|
|
272
281
|
specify 'runtime halt in jq raises error' do
|
273
|
-
expect
|
282
|
+
expect do
|
274
283
|
JQ('{}').search('.data | keys') do |value|
|
275
284
|
value
|
276
285
|
end
|
277
|
-
|
286
|
+
end.to raise_error(JQ::Error).with_message('null (null) has no keys')
|
278
287
|
end
|
279
288
|
|
280
289
|
specify 'query for hash' do
|
281
|
-
src = {'FOO' => 100, 'BAR' => [200, 200]}
|
290
|
+
src = { 'FOO' => 100, 'BAR' => [200, 200] }
|
282
291
|
|
283
292
|
expect(src.jq('.BAR[]')).to eq([200, 200])
|
284
293
|
|
@@ -298,10 +307,10 @@ describe JQ do
|
|
298
307
|
end
|
299
308
|
|
300
309
|
specify 'error in block' do
|
301
|
-
expect
|
302
|
-
JQ('[1,2,3]').search('.[]') do |
|
310
|
+
expect do
|
311
|
+
JQ('[1,2,3]').search('.[]') do |_value|
|
303
312
|
1 / 0
|
304
313
|
end
|
305
|
-
|
314
|
+
end.to raise_error(ZeroDivisionError)
|
306
315
|
end
|
307
316
|
end
|
data/spec/spec_helper.rb
CHANGED
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: ruby-jq
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- winebarrel
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-06-
|
11
|
+
date: 2019-06-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: multi_json
|
@@ -80,6 +80,20 @@ dependencies:
|
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
82
|
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: rubocop
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
83
97
|
description: Ruby bindings for jq
|
84
98
|
email: sgwr_dts@yahoo.co.jp
|
85
99
|
executables: []
|
@@ -89,6 +103,7 @@ extra_rdoc_files: []
|
|
89
103
|
files:
|
90
104
|
- ".gitignore"
|
91
105
|
- ".rspec"
|
106
|
+
- ".rubocop.yml"
|
92
107
|
- ".travis.yml"
|
93
108
|
- Gemfile
|
94
109
|
- LICENSE.txt
|