ss2json 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/Changelog +10 -0
- data/README.md +84 -27
- data/Rakefile +7 -0
- data/lib/ss2json/cli.rb +13 -1
- data/lib/ss2json/options.rb +7 -1
- data/lib/ss2json/row_converter.rb +20 -6
- data/lib/ss2json/version.rb +1 -1
- data/test/row_converter_test.rb +60 -0
- metadata +68 -44
- data/CHANGELOG +0 -5
data/Changelog
ADDED
data/README.md
CHANGED
@@ -1,11 +1,16 @@
|
|
1
1
|
|
2
2
|
# ss2json
|
3
3
|
|
4
|
+
|
4
5
|
**ss2json** is a SpreadSheet To Json converter. It follow a few rules for generating nested hash.
|
5
6
|
|
7
|
+
## Tutorial
|
8
|
+
|
9
|
+
### Step 1
|
10
|
+
|
6
11
|
For example, this document:
|
7
12
|
|
8
|
-
![Excel](https://github.com/
|
13
|
+
![Excel](https://github.com/wooga/ss2json/raw/master/doc/ss2json-2.png "Title is optional")
|
9
14
|
|
10
15
|
We download as an OpenOffice document (ods), and run:
|
11
16
|
|
@@ -13,45 +18,92 @@ We download as an OpenOffice document (ods), and run:
|
|
13
18
|
|
14
19
|
Will converted in this:
|
15
20
|
|
16
|
-
```
|
21
|
+
```javascript
|
22
|
+
[
|
23
|
+
{
|
24
|
+
"id": 1,
|
25
|
+
"name": { "first": "Guillermo", "last": "Alvarez" },
|
26
|
+
"child": [ { "name": "pepe", "age": 2 }, { "name": "Juanjo" } ]
|
27
|
+
},
|
28
|
+
{
|
29
|
+
"id": 2,
|
30
|
+
"name": { "first": "Martin", "last": "Luther" },
|
31
|
+
"child": [ { "name": "Jr" } ]
|
32
|
+
},
|
33
|
+
{
|
34
|
+
"id": 3,
|
35
|
+
"name": { "first": "Jesper" }
|
36
|
+
},
|
37
|
+
{ "id": 4 },
|
38
|
+
{ "id": 5 },
|
39
|
+
{ "id": 6 }
|
40
|
+
]
|
41
|
+
```
|
42
|
+
|
43
|
+
### Step 2
|
44
|
+
|
45
|
+
We want to remove the last columns, so we need to tell **ss2json** to check for the name. We do that with the __-c__ parameter.
|
46
|
+
|
47
|
+
```
|
48
|
+
ss2json -f documents.ods -c name
|
49
|
+
```
|
50
|
+
|
51
|
+
```javascript
|
17
52
|
[
|
18
53
|
{
|
19
54
|
"id": 1,
|
20
|
-
"name": {
|
21
|
-
|
22
|
-
"last": "Alvarez"
|
23
|
-
},
|
24
|
-
"child": [
|
25
|
-
{
|
26
|
-
"name": "pepe",
|
27
|
-
"age": 2
|
28
|
-
},
|
29
|
-
{
|
30
|
-
"name": "Juanjo"
|
31
|
-
}
|
32
|
-
]
|
55
|
+
"name": { "first": "Guillermo", "last": "Alvarez" },
|
56
|
+
"child": [ { "name": "pepe", "age": 2 }, { "name": "Juanjo" } ]
|
33
57
|
},
|
34
58
|
{
|
35
59
|
"id": 2,
|
36
|
-
"name": {
|
37
|
-
|
38
|
-
"last": "Luther"
|
39
|
-
},
|
40
|
-
"child": [
|
41
|
-
{
|
42
|
-
"name": "Jr"
|
43
|
-
}
|
44
|
-
]
|
60
|
+
"name": { "first": "Martin","last": "Luther"},
|
61
|
+
"child": [{"name": "Jr"}]
|
45
62
|
},
|
46
63
|
{
|
47
64
|
"id": 3,
|
48
|
-
"name": {
|
49
|
-
"first": "Jesper"
|
50
|
-
}
|
65
|
+
"name": {"first": "Jesper"}
|
51
66
|
}
|
52
67
|
]
|
53
68
|
```
|
54
69
|
|
70
|
+
### Step 3
|
71
|
+
|
72
|
+
We have a crappy parser, and need to include blank_fieds, so we say that to ss2json.
|
73
|
+
|
74
|
+
```
|
75
|
+
ss2json -f documents.ods -c name -b
|
76
|
+
```
|
77
|
+
|
78
|
+
|
79
|
+
### Step 4
|
80
|
+
|
81
|
+
We have the rows with the title in colum 3, as in:
|
82
|
+
|
83
|
+
![Excel](https://github.com/wooga/ss2json/raw/master/doc/ss2json-1.png "Title is optional")
|
84
|
+
|
85
|
+
So we say to **ss2json** to start parsing in the row tree:
|
86
|
+
|
87
|
+
```
|
88
|
+
ss2json -f documents.ods -c name -r 3
|
89
|
+
```
|
90
|
+
|
91
|
+
### Step 5
|
92
|
+
|
93
|
+
We don't want to open the file to have a list of the sheets:
|
94
|
+
|
95
|
+
```
|
96
|
+
ss2json -f documents.ods -l
|
97
|
+
```
|
98
|
+
|
99
|
+
|
100
|
+
|
101
|
+
## Support
|
102
|
+
|
103
|
+
Right now ss2json supports ods and xlsx files.
|
104
|
+
|
105
|
+
|
106
|
+
|
55
107
|
## Install
|
56
108
|
|
57
109
|
gem install ss2json
|
@@ -78,6 +130,11 @@ Usage: ss2json -f FILENAME [options]
|
|
78
130
|
-h, --help Show this help
|
79
131
|
```
|
80
132
|
|
133
|
+
## TODO
|
134
|
+
|
135
|
+
* Support all the document formats from **roo** librarly.
|
136
|
+
* -c options should be able to check inside the hash, for example name.first should check {"name":{"first": null}}
|
137
|
+
|
81
138
|
## License
|
82
139
|
|
83
140
|
BSD
|
data/Rakefile
CHANGED
data/lib/ss2json/cli.rb
CHANGED
@@ -6,16 +6,28 @@ class Ss2Json
|
|
6
6
|
class Cli
|
7
7
|
attr_reader :content, :doc
|
8
8
|
|
9
|
+
# Parse the options from ARGV, initialize the conversion, and return the string with the output
|
9
10
|
def self.start
|
10
11
|
options = Ss2Json::Options.parse!
|
11
12
|
converter = new(options)
|
12
|
-
|
13
|
+
case options[:action]
|
14
|
+
when :list
|
13
15
|
converter.doc.sheets.join("\n")
|
14
16
|
else
|
15
17
|
JSON.pretty_generate(converter.content)
|
16
18
|
end
|
17
19
|
end
|
18
20
|
|
21
|
+
# Create a new converter the options are:
|
22
|
+
#
|
23
|
+
# * **:file** Input file.
|
24
|
+
# * **:sheet** Name of the sheet to use.
|
25
|
+
# * **:first_row** Where the title of the columns is.
|
26
|
+
# * **:check_column** Output only the results with a value present on the specific field.
|
27
|
+
# * **:action** Could
|
28
|
+
# * *:convert* Do the normal conversion.
|
29
|
+
# * *:list* Will list the sheets.
|
30
|
+
# * **:converter**: Options passed to the converter: Ss2Json::RowConverter
|
19
31
|
def initialize(options)
|
20
32
|
@options = options
|
21
33
|
init_document
|
data/lib/ss2json/options.rb
CHANGED
@@ -9,10 +9,12 @@ class Ss2Json
|
|
9
9
|
:sheet => nil,
|
10
10
|
:file => nil,
|
11
11
|
:check_column => nil,
|
12
|
+
:action => :convert,
|
12
13
|
:converter => {
|
13
14
|
:show_null => false,
|
14
15
|
:dont_convert => false,
|
15
|
-
:ignored_values => []
|
16
|
+
:ignored_values => [],
|
17
|
+
:downcase_first_letter => true
|
16
18
|
}
|
17
19
|
|
18
20
|
}
|
@@ -59,6 +61,10 @@ class Ss2Json
|
|
59
61
|
@options[:converter][:dont_convert] = true
|
60
62
|
end
|
61
63
|
|
64
|
+
opts.on("-l", "--disable-first-letter", "Will disable the downcase of the first letter of the key") do
|
65
|
+
@options[:converter][:downcase_first_letter] = false
|
66
|
+
end
|
67
|
+
|
62
68
|
opts.separator ""
|
63
69
|
|
64
70
|
opts.on("-l", "--list-sheets", "Return the list of sheets") do |file|
|
@@ -3,6 +3,14 @@ require 'nested_hash'
|
|
3
3
|
class Ss2Json
|
4
4
|
class RowConverter < NestedHash
|
5
5
|
|
6
|
+
# Create a nested_hash from a hash with just one level (key,value).
|
7
|
+
#
|
8
|
+
# The options are:
|
9
|
+
#
|
10
|
+
# * **:ignored_values** Array of ignored values.
|
11
|
+
# * **:show_null** Export the keys with empty values.
|
12
|
+
# * **:dont_convert** Convert 10.0 float values to integers.
|
13
|
+
# * **:downcase_first_letter** Convert to downcase the first letter of each key.
|
6
14
|
def initialize(hash, options={})
|
7
15
|
@options = options
|
8
16
|
super(hash)
|
@@ -18,24 +26,30 @@ class Ss2Json
|
|
18
26
|
false
|
19
27
|
end
|
20
28
|
|
21
|
-
def sanitize_value(v)
|
22
|
-
return v if @options[:dont_convert]
|
23
|
-
end
|
24
|
-
|
25
29
|
def process(key,value)
|
26
30
|
super if valid_value?(value)
|
27
31
|
end
|
28
32
|
|
29
33
|
def valid_value?(value)
|
30
|
-
|
31
|
-
(@options[:show_null] || value )
|
34
|
+
@options[:show_null] || !ignored_values.include?(value)
|
32
35
|
end
|
33
36
|
|
37
|
+
def ignored_values
|
38
|
+
(@options[:ignored_values] || []) << nil
|
39
|
+
end
|
40
|
+
|
41
|
+
|
34
42
|
def sanitize_value(v)
|
35
43
|
return v if @options[:dont_convert]
|
36
44
|
return v.to_i if v.is_a?(Float) && v % 1 == 0
|
37
45
|
v
|
38
46
|
end
|
39
47
|
|
48
|
+
def sanitize_key(key)
|
49
|
+
return key unless is_valid_key?(key)
|
50
|
+
key = key[0..1].downcase + key[2..-1] if @options[:downcase_first_letter]
|
51
|
+
key
|
52
|
+
end
|
53
|
+
|
40
54
|
end
|
41
55
|
end
|
data/lib/ss2json/version.rb
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
|
2
|
+
require 'ss2json'
|
3
|
+
require 'test/unit'
|
4
|
+
|
5
|
+
class Ss2Json::RowConverterTest < Test::Unit::TestCase
|
6
|
+
|
7
|
+
def test_class
|
8
|
+
nested_hash = Ss2Json::RowConverter.new({})
|
9
|
+
nested_hash.is_a?(Hash)
|
10
|
+
end
|
11
|
+
|
12
|
+
def test_ignored_values_option
|
13
|
+
options = {:ignored_values => ["???"]}
|
14
|
+
new_hash = Ss2Json::RowConverter.new({"adsf" => '???'},options)
|
15
|
+
assert_equal({}, new_hash)
|
16
|
+
new_hash = Ss2Json::RowConverter.new({"asdf" => 'asdf'}, options)
|
17
|
+
assert_equal({"asdf" => 'asdf' }, new_hash)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_show_null_option
|
21
|
+
initial_hash = {"asdf" => nil}
|
22
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash,{:show_null => false})
|
23
|
+
assert_equal({}, new_hash)
|
24
|
+
|
25
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash,{:show_null => true})
|
26
|
+
assert_equal({"asdf" => nil}, new_hash)
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_dont_convert_option
|
30
|
+
initial_hash = { "asdf" => 3.0 }
|
31
|
+
|
32
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash, {:dont_convert => true})
|
33
|
+
assert_equal(initial_hash, new_hash)
|
34
|
+
|
35
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash, {:dont_convert => false})
|
36
|
+
assert_equal(initial_hash, { "asdf" => 3 })
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_downcase_first_letter
|
40
|
+
initial_hash = { "Asdf.pepe" => 3, "asdf.Jose" => 5 }
|
41
|
+
|
42
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash, {:downcase_first_letter => false})
|
43
|
+
assert_equal({"Asdf"=>{"pepe"=>3}, "asdf"=>{"Jose"=>5}}, new_hash)
|
44
|
+
|
45
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash, {:downcase_first_letter => true})
|
46
|
+
assert_equal({"asdf" => {"pepe" => 3, "jose" => 5}}, new_hash)
|
47
|
+
end
|
48
|
+
|
49
|
+
def test_it_ignore_ignored_fields
|
50
|
+
initial_hash = { "i.asdf" => 5}
|
51
|
+
|
52
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash)
|
53
|
+
assert_equal({}, new_hash)
|
54
|
+
|
55
|
+
initial_hash = { "name.i" => 5}
|
56
|
+
|
57
|
+
new_hash = Ss2Json::RowConverter.new(initial_hash)
|
58
|
+
assert_equal({"name" => {"i" => 5}}, new_hash)
|
59
|
+
end
|
60
|
+
end
|
metadata
CHANGED
@@ -1,48 +1,63 @@
|
|
1
|
-
--- !ruby/object:Gem::Specification
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
2
|
name: ss2json
|
3
|
-
version: !ruby/object:Gem::Version
|
4
|
-
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
6
11
|
platform: ruby
|
7
|
-
authors:
|
8
|
-
- Guillermo A
|
12
|
+
authors:
|
13
|
+
- "Guillermo A\xCC\x81lvarez"
|
9
14
|
autorequire:
|
10
15
|
bindir: bin
|
11
16
|
cert_chain: []
|
12
|
-
|
13
|
-
|
14
|
-
|
17
|
+
|
18
|
+
date: 2012-05-23 00:00:00 +00:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
15
22
|
name: nested_hash
|
16
|
-
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
17
25
|
none: false
|
18
|
-
requirements:
|
19
|
-
- -
|
20
|
-
- !ruby/object:Gem::Version
|
21
|
-
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
22
33
|
type: :runtime
|
23
|
-
|
24
|
-
|
25
|
-
- !ruby/object:Gem::Dependency
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
26
36
|
name: roo
|
27
|
-
|
37
|
+
prerelease: false
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
|
-
requirements:
|
30
|
-
- -
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
|
40
|
+
requirements:
|
41
|
+
- - ">="
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 3
|
44
|
+
segments:
|
45
|
+
- 0
|
46
|
+
version: "0"
|
33
47
|
type: :runtime
|
34
|
-
|
35
|
-
version_requirements: *70291603210920
|
48
|
+
version_requirements: *id002
|
36
49
|
description: Convert SpreadSheet documents to json following some conventions.
|
37
|
-
email:
|
50
|
+
email:
|
38
51
|
- guillermo@cientifico.net
|
39
|
-
executables:
|
52
|
+
executables:
|
40
53
|
- ss2json
|
41
54
|
extensions: []
|
55
|
+
|
42
56
|
extra_rdoc_files: []
|
43
|
-
|
57
|
+
|
58
|
+
files:
|
44
59
|
- .gitignore
|
45
|
-
-
|
60
|
+
- Changelog
|
46
61
|
- Gemfile
|
47
62
|
- README.md
|
48
63
|
- Rakefile
|
@@ -55,34 +70,43 @@ files:
|
|
55
70
|
- lib/ss2json/row_converter.rb
|
56
71
|
- lib/ss2json/version.rb
|
57
72
|
- ss2json.gemspec
|
73
|
+
- test/row_converter_test.rb
|
58
74
|
- test/ss2json (1).ods
|
59
75
|
- test/ss2json.ods
|
60
76
|
- test/ss2json.xls
|
61
|
-
|
77
|
+
has_rdoc: true
|
78
|
+
homepage: ""
|
62
79
|
licenses: []
|
80
|
+
|
63
81
|
post_install_message:
|
64
82
|
rdoc_options: []
|
65
|
-
|
83
|
+
|
84
|
+
require_paths:
|
66
85
|
- lib
|
67
|
-
required_ruby_version: !ruby/object:Gem::Requirement
|
86
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
68
87
|
none: false
|
69
|
-
requirements:
|
70
|
-
- -
|
71
|
-
- !ruby/object:Gem::Version
|
72
|
-
|
73
|
-
|
88
|
+
requirements:
|
89
|
+
- - ">="
|
90
|
+
- !ruby/object:Gem::Version
|
91
|
+
hash: 3
|
92
|
+
segments:
|
93
|
+
- 0
|
94
|
+
version: "0"
|
95
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
74
96
|
none: false
|
75
|
-
requirements:
|
76
|
-
- -
|
77
|
-
- !ruby/object:Gem::Version
|
78
|
-
|
97
|
+
requirements:
|
98
|
+
- - ">="
|
99
|
+
- !ruby/object:Gem::Version
|
100
|
+
hash: 3
|
101
|
+
segments:
|
102
|
+
- 0
|
103
|
+
version: "0"
|
79
104
|
requirements: []
|
105
|
+
|
80
106
|
rubyforge_project: ss2json
|
81
|
-
rubygems_version: 1.
|
107
|
+
rubygems_version: 1.6.2
|
82
108
|
signing_key:
|
83
109
|
specification_version: 3
|
84
110
|
summary: SpreadSheet to Json convert
|
85
|
-
test_files:
|
86
|
-
|
87
|
-
- test/ss2json.ods
|
88
|
-
- test/ss2json.xls
|
111
|
+
test_files: []
|
112
|
+
|