ss2json 0.3.2 → 1.0.0.pre
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 +29 -2
- data/Rakefile +12 -4
- data/balance.xlsx +0 -0
- data/bin/ss2json +38 -3
- data/lib/ss2json-commands/cat.rb +71 -0
- data/lib/ss2json-commands/compress.rb +67 -0
- data/lib/ss2json-commands/constants.rb +132 -0
- data/lib/ss2json-commands/humanize.rb +72 -0
- data/lib/ss2json-commands/ls.rb +71 -0
- data/lib/ss2json-commands/merge.rb +87 -0
- data/lib/ss2json-commands/to_array.rb +128 -0
- data/lib/ss2json-commands/to_hash.rb +137 -0
- data/lib/ss2json/command.rb +22 -0
- data/lib/ss2json/converter.rb +95 -0
- data/lib/ss2json/row_converter.rb +1 -2
- data/lib/ss2json/version.rb +2 -2
- data/ss2json.gemspec +13 -2
- data/test/catss.fixture +9 -0
- data/test/catss2.fixture +7 -0
- data/test/cli_test.rb +61 -0
- data/test/integration_test.rb +90 -0
- data/test/row_converter_test.rb +0 -12
- data/test/ss2json.xls +0 -0
- metadata +65 -27
- data/bin/merge_jsons +0 -32
- data/lib/ss2json.rb +0 -8
- data/lib/ss2json/cli.rb +0 -120
- data/lib/ss2json/options.rb +0 -146
data/README.md
CHANGED
@@ -1,8 +1,35 @@
|
|
1
|
-
|
2
1
|
# ss2json
|
3
2
|
|
3
|
+
**ss2json** is a collection of tools to help in the conversion of spreadsheet to json.
|
4
|
+
|
5
|
+
* [ss2json-vertical](#ss2json-vertical) Generate an array of rows. Each row is going to be a hash.
|
6
|
+
* [ss2json-vertical-hash](#ss2json-vertical-hash) Generate a hash of elements. Each element is a hash that represents a column. The key of that hash is a column.
|
7
|
+
* [ss2json-horizontal](#ss2json-horizontal) Generate a hash from a key value pairs. The keys are in one column and the values in other.
|
8
|
+
* [merge-jsons](#merge-jsons) Generate a hash that have the filename as a key, and the content as a value.
|
9
|
+
* [order-json](#order-jsons) Order the keys of the hashes of a json file.
|
10
|
+
* [compress-json](#compress-json) Compress the given json. The lasts commands output in pretty format (human readable). You can pipe through this command to compress.
|
11
|
+
* [catss](#catss) Shows on the terminal the content of the sheet
|
12
|
+
|
13
|
+
## Tools
|
14
|
+
|
15
|
+
### ss2json-vertical
|
16
|
+
|
17
|
+
Lets start with this command to show the basic feature of ss2json.
|
18
|
+
Suppose we have this sheet:
|
19
|
+
|
20
|
+
| A | B | C | D | E | F | G | H | I |
|
21
|
+
1 | id | name | childs.1.name | childs.1.age | childs.2.name | Childs.2.age | address.street | address.post_code | i.notes |
|
22
|
+
2 | 1 | Guillermo | | | | | Calle de Eros 7 | 28018 | nice guy |
|
23
|
+
3 | 2 | Epi | Carlos | | | | Castellana | 28020 | |
|
24
|
+
4 | 3 | Esther | Roberto | 3 | Carlos | 4 | | | |
|
25
|
+
5 | 4 | | | | | | | | left note |
|
26
|
+
|
27
|
+
What we see here is that the column names (row 1) have a special encoding.
|
28
|
+
|
29
|
+
### ss2json-hash
|
30
|
+
|
31
|
+
### ss2json-horizontal
|
4
32
|
|
5
|
-
**ss2json** is a SpreadSheet To Json converter. It follow a few rules for generating nested hash.
|
6
33
|
|
7
34
|
## Tutorial
|
8
35
|
|
data/Rakefile
CHANGED
@@ -1,8 +1,16 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
|
+
require 'rubygems'
|
3
|
+
require 'bundler/setup'
|
2
4
|
|
3
5
|
|
4
6
|
|
5
|
-
desc "test"
|
6
|
-
task :test do
|
7
|
-
|
8
|
-
end
|
7
|
+
# desc "test"
|
8
|
+
# task :test do
|
9
|
+
# sh "ruby -I lib -rubygems test/**/*_test.rb"
|
10
|
+
# end
|
11
|
+
|
12
|
+
# require 'rake/testtask'
|
13
|
+
#
|
14
|
+
# Rake::TestTask.new do |t|
|
15
|
+
# t.pattern = "test/**/*_test.rb"
|
16
|
+
# end
|
data/balance.xlsx
ADDED
Binary file
|
data/bin/ss2json
CHANGED
@@ -1,7 +1,42 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
if ARGV[0] && !(ARGV[0] =~ /^-/)
|
4
|
+
begin
|
5
|
+
require "ss2json-commands/#{ARGV[0]}"
|
6
|
+
kommand = SS2JSON::Command.const_get(ARGV[0].gsub(/^.|_./){|a| a[-1].chr.upcase})
|
7
|
+
$0="#{$0} #{ARGV[0]}"
|
8
|
+
$stderr.puts "ss2json: '#{ARGV[0]}' is not a ss2json command. See 'ss2json --help'. (#{e.message})"
|
9
|
+
exit -1
|
10
|
+
end
|
11
|
+
else
|
5
12
|
|
13
|
+
require 'ss2json/command'
|
14
|
+
require 'optparse'
|
6
15
|
|
7
|
-
|
16
|
+
available_commands = []
|
17
|
+
SS2JSON::Command.load_all
|
18
|
+
SS2JSON::Command.commands.each do |command|
|
19
|
+
available_commands << [command.name, command.description]
|
20
|
+
end
|
21
|
+
|
22
|
+
opts = OptionParser.new do |opts|
|
23
|
+
opts.banner = "Usage: #{$0} ACTION [options]"
|
24
|
+
|
25
|
+
opts.separator ""
|
26
|
+
opts.separator "Where ACTION could be:"
|
27
|
+
available_commands.each do |cmd|
|
28
|
+
opts.separator "\t%-10s%s" % cmd
|
29
|
+
end
|
30
|
+
opts.separator ""
|
31
|
+
|
32
|
+
opts.on("-h", "--help", "Show this help") do
|
33
|
+
puts opts
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
ARGV[0] = "--help" if ARGV.size == 0
|
38
|
+
opts.parse!(ARGV)
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
require 'ss2json/command'
|
6
|
+
require 'ss2json/converter'
|
7
|
+
require 'optparse'
|
8
|
+
require 'terminal-table'
|
9
|
+
require 'json'
|
10
|
+
|
11
|
+
class Cat < SS2JSON::Command
|
12
|
+
|
13
|
+
def self.name
|
14
|
+
"cat"
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.description
|
18
|
+
"Shows a nice console friendly table of the sheet"
|
19
|
+
end
|
20
|
+
|
21
|
+
def initialize(options)
|
22
|
+
options = Options.new(options).options
|
23
|
+
converter = SS2JSON::Converter.new(options)
|
24
|
+
puts ::Terminal::Table.new :rows => converter.to_a
|
25
|
+
end
|
26
|
+
|
27
|
+
class Options < ::OptionParser
|
28
|
+
attr_reader :options
|
29
|
+
DEFAULT_OPTIONS = {
|
30
|
+
:sheet => nil,
|
31
|
+
:file => nil,
|
32
|
+
}
|
33
|
+
|
34
|
+
def initialize(args)
|
35
|
+
@options = DEFAULT_OPTIONS
|
36
|
+
@help = nil
|
37
|
+
super() do |opts|
|
38
|
+
@help = opts
|
39
|
+
|
40
|
+
opts.banner = "Usage: #{$0} FILENAME [sheet]"
|
41
|
+
|
42
|
+
opts.separator "\n"
|
43
|
+
|
44
|
+
opts.on_tail("-h","--help", "Show this help") do
|
45
|
+
puts opts
|
46
|
+
exit 0
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on_tail("--version", "Show the version") do
|
50
|
+
require 'ss2json/version'
|
51
|
+
puts "#{$0} Version: #{SS2JSON::VERSION}"
|
52
|
+
exit 0
|
53
|
+
end
|
54
|
+
end.parse!(args)
|
55
|
+
|
56
|
+
if file = args.shift
|
57
|
+
@options[:file] = file
|
58
|
+
@options[:sheet] = args.shift
|
59
|
+
else
|
60
|
+
die("Incorrect number of parameters")
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def die(msg)
|
65
|
+
$stderr.puts msg
|
66
|
+
$stderr.puts @help
|
67
|
+
exit -1
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'ss2json/command'
|
2
|
+
require 'optparse'
|
3
|
+
|
4
|
+
class Compress < SS2JSON::Command
|
5
|
+
|
6
|
+
def self.name
|
7
|
+
"compress"
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.description
|
11
|
+
"Uglify a json file (DO NOT RESPECT ORDER)"
|
12
|
+
end
|
13
|
+
|
14
|
+
def initialize(options)
|
15
|
+
options = Options.new(options).options
|
16
|
+
puts JSON.parse(options[:file].read).to_json
|
17
|
+
ensure
|
18
|
+
options[:file].close if options[:file]
|
19
|
+
end
|
20
|
+
|
21
|
+
class Options < ::OptionParser
|
22
|
+
attr_reader :options
|
23
|
+
DEFAULT_OPTIONS = {
|
24
|
+
:sheet => nil,
|
25
|
+
:file => nil,
|
26
|
+
}
|
27
|
+
|
28
|
+
def initialize(args)
|
29
|
+
@options = DEFAULT_OPTIONS
|
30
|
+
opts = super() do |opts|
|
31
|
+
@help = opts
|
32
|
+
|
33
|
+
opts.banner = "Usage: #{$0} [FILENAME]"
|
34
|
+
|
35
|
+
opts.separator "\n"
|
36
|
+
|
37
|
+
opts.on_tail("-h","--help", "Show this help") do
|
38
|
+
puts opts
|
39
|
+
exit 0
|
40
|
+
end
|
41
|
+
|
42
|
+
opts.on_tail("--version", "Show the version") do
|
43
|
+
require 'ss2json/version'
|
44
|
+
puts "#{$0} Version: #{SS2JSON::VERSION}"
|
45
|
+
exit 0
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
opts.parse!(args)
|
50
|
+
|
51
|
+
if args.size > 1
|
52
|
+
file = args.first
|
53
|
+
File.file?(file) or die("File #{file} not found")
|
54
|
+
@options[:file] = File.open(file)
|
55
|
+
else
|
56
|
+
@options[:file] = $stdin
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def die(msg)
|
61
|
+
$stderr.puts msg
|
62
|
+
$stderr.puts @help
|
63
|
+
exit -1
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -0,0 +1,132 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
require 'ss2json/command'
|
4
|
+
require 'ss2json/converter'
|
5
|
+
require 'optparse'
|
6
|
+
require 'json'
|
7
|
+
|
8
|
+
class Constants < SS2JSON::Command
|
9
|
+
|
10
|
+
def self.name
|
11
|
+
"constants"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.description
|
15
|
+
"Convert a spreadsheet to a json hash where the keys are in one column and the values are in another column"
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(options)
|
19
|
+
options = Options.new(options).options
|
20
|
+
output = Converter.new(options).process
|
21
|
+
puts JSON.pretty_generate(output)
|
22
|
+
end
|
23
|
+
|
24
|
+
class Options < OptionParser
|
25
|
+
attr_reader :options
|
26
|
+
DEFAULT_OPTIONS = {
|
27
|
+
:first_row => 1,
|
28
|
+
:sheet => nil,
|
29
|
+
:file => nil,
|
30
|
+
:key_column => 1,
|
31
|
+
:value_column => 2,
|
32
|
+
:converter => {
|
33
|
+
:show_null => false,
|
34
|
+
:dont_convert => false,
|
35
|
+
:ignored_values => [],
|
36
|
+
:downcase_first_letter => true
|
37
|
+
}
|
38
|
+
|
39
|
+
}
|
40
|
+
|
41
|
+
def initialize(args)
|
42
|
+
@options = DEFAULT_OPTIONS
|
43
|
+
@help = nil
|
44
|
+
super() do |opts|
|
45
|
+
@help = opts
|
46
|
+
|
47
|
+
opts.banner = "Usage: #{$0} FILENAME [options]"
|
48
|
+
|
49
|
+
opts.on("-s", "--sheet SHEET_NAME", "Use other that the first table") do |sheet|
|
50
|
+
@options[:sheet] = sheet
|
51
|
+
end
|
52
|
+
|
53
|
+
opts.on("-r", "--first-row ROW_NUMBER", "Set the first row") do |row|
|
54
|
+
die("Can't understand the row #{row}. Use a number") unless row =~ /\A\d*\z/
|
55
|
+
@options[:first_row] = row.to_i
|
56
|
+
end
|
57
|
+
|
58
|
+
|
59
|
+
opts.on("-k", "--key-column COLUMN_NUMBER", "Column where the keys are (Default to 1)") do |column|
|
60
|
+
die("Can't understand the column #{column}. Use a number") unless column =~ /\A\d*\z/
|
61
|
+
@options[:key_column] = column.to_i
|
62
|
+
end
|
63
|
+
|
64
|
+
opts.on("-a", "--value-column COLUMN_NUMBER", "Column where the values are (Default to 2)") do |column|
|
65
|
+
die("Can't understand the column #{column}. Use a number") unless column =~ /\A\d*\z/
|
66
|
+
@options[:value_column] = column.to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
opts.separator "\nData options:"
|
70
|
+
|
71
|
+
opts.on("-i", "--ignore-value VALUE", "Ignore the fields with that value. Could be use several times") do |t|
|
72
|
+
@options[:converter][:ignored_values] << t
|
73
|
+
end
|
74
|
+
|
75
|
+
opts.on("-b", "--include-blank", "Generate a json with the values included in the ignore list") do |t|
|
76
|
+
@options[:converter][:show_null] = true
|
77
|
+
end
|
78
|
+
|
79
|
+
opts.on("-d", "--disable-conversion", "Disable the conversion from floats to integers") do
|
80
|
+
@options[:converter][:dont_convert] = true
|
81
|
+
end
|
82
|
+
|
83
|
+
opts.on("-l", "--disable-first-letter", "Will disable the downcase of the first letter of the key") do
|
84
|
+
@options[:converter][:downcase_first_letter] = false
|
85
|
+
end
|
86
|
+
|
87
|
+
|
88
|
+
opts.separator "\n"
|
89
|
+
|
90
|
+
opts.on_tail("-h","--help", "Show this help") do
|
91
|
+
puts opts
|
92
|
+
exit 0
|
93
|
+
end
|
94
|
+
|
95
|
+
opts.on_tail("--version", "Show the version") do
|
96
|
+
puts "#{File.basename($0)} Version: #{SS2JSON::VERSION}"
|
97
|
+
exit 0
|
98
|
+
end
|
99
|
+
|
100
|
+
end.parse!(args)
|
101
|
+
|
102
|
+
if args.size == 1
|
103
|
+
@options[:file] = args.first
|
104
|
+
unless File.file?(@options[:file])
|
105
|
+
$stderr.puts "File #{@options.file} not found"
|
106
|
+
exit -5
|
107
|
+
end
|
108
|
+
else
|
109
|
+
die("Incorrect number of parameters")
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def die(msg)
|
114
|
+
$stderr.puts msg
|
115
|
+
$stderr.puts @help
|
116
|
+
exit -1
|
117
|
+
end
|
118
|
+
end
|
119
|
+
|
120
|
+
class Converter < SS2JSON::Converter
|
121
|
+
def process
|
122
|
+
hash = {}
|
123
|
+
each_row do |row|
|
124
|
+
key = @doc.cell(row, @options[:key_column])
|
125
|
+
value = @doc.cell(row, @options[:value_column])
|
126
|
+
hash[key] = value
|
127
|
+
end
|
128
|
+
@content = SS2JSON::RowConverter.new(hash, @options[:converter])
|
129
|
+
@content
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
require 'ss2json/command'
|
6
|
+
require 'optparse'
|
7
|
+
|
8
|
+
class Humanize < SS2JSON::Command
|
9
|
+
|
10
|
+
def self.name
|
11
|
+
"humanize"
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.description
|
15
|
+
"Pretty print and sort (keys) on json"
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(options)
|
19
|
+
options = Options.new(options).options
|
20
|
+
if options[:file]
|
21
|
+
exec "python -mjson.tool < '#{options[:file]}'"
|
22
|
+
else
|
23
|
+
exec "python -mjson.tool"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
class Options < ::OptionParser
|
28
|
+
attr_reader :options
|
29
|
+
DEFAULT_OPTIONS = {
|
30
|
+
:sheet => nil,
|
31
|
+
:file => nil,
|
32
|
+
}
|
33
|
+
|
34
|
+
def initialize(args)
|
35
|
+
@options = DEFAULT_OPTIONS
|
36
|
+
opts = super() do |opts|
|
37
|
+
@help = opts
|
38
|
+
|
39
|
+
opts.banner = "Usage: #{$0} [FILENAME]"
|
40
|
+
|
41
|
+
opts.separator "\n"
|
42
|
+
opts.separator "\tThis tool use python -mjson.tool So you need python to be installed\n"
|
43
|
+
|
44
|
+
opts.on_tail("-h","--help", "Show this help") do
|
45
|
+
puts opts
|
46
|
+
exit 0
|
47
|
+
end
|
48
|
+
|
49
|
+
opts.on_tail("--version", "Show the version") do
|
50
|
+
require 'ss2json/version'
|
51
|
+
puts "#{$0} Version: #{SS2JSON::VERSION}"
|
52
|
+
exit 0
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
opts.parse!(args)
|
57
|
+
|
58
|
+
if args.size > 1
|
59
|
+
file = args.first
|
60
|
+
File.file?(file) or die("File #{file} not found")
|
61
|
+
@options[:file] = file
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def die(msg)
|
66
|
+
$stderr.puts msg
|
67
|
+
$stderr.puts @help
|
68
|
+
exit -1
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|