csv2json 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.document ADDED
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
data/.gitignore ADDED
@@ -0,0 +1,21 @@
1
+ ## MAC OS
2
+ .DS_Store
3
+
4
+ ## TEXTMATE
5
+ *.tmproj
6
+ tmtags
7
+
8
+ ## EMACS
9
+ *~
10
+ \#*
11
+ .\#*
12
+
13
+ ## VIM
14
+ *.swp
15
+
16
+ ## PROJECT::GENERAL
17
+ coverage
18
+ rdoc
19
+ pkg
20
+
21
+ ## PROJECT::SPECIFIC
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Antonin Hildebrand
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,105 @@
1
+ = csv2json
2
+
3
+ Clients were sending me XLS files, but my webs consume JSON. So I needed to convert them to JSON easily from command-line.
4
+ Tried to google for solution and surprisingly enough nothing solid existed.
5
+
6
+ == Solution
7
+
8
+ - export XLS as a CSV file (I use OpenOffice.org for this)
9
+ - run `csv2json file.csv > file.json`
10
+ - there is no step 3
11
+
12
+ === Sample
13
+
14
+ note: make sure your XLS table has the first row with column names
15
+
16
+ This CSV file:
17
+
18
+ thumbpath,imgpath,imgsrc,width,height,thumbsrc,thumbwidth,thumbheight
19
+ thumbnails/,images/,paris_01.jpg,350,262,paris_01.jpg,75,56
20
+ thumbnails/,images/,paris_02.jpg,262,350,paris_02.jpg,75,56
21
+
22
+ gets turned into this JSON:
23
+
24
+ [
25
+ {
26
+ "thumbwidth": 75,
27
+ "imgsrc": "paris_01.jpg",
28
+ "thumbsrc": "paris_01.jpg",
29
+ "height": 262,
30
+ "imgpath": "images/",
31
+ "thumbheight": 56,
32
+ "thumbpath": "thumbnails/",
33
+ "width": 350
34
+ },
35
+ {
36
+ "thumbwidth": 75,
37
+ "imgsrc": "paris_02.jpg",
38
+ "thumbsrc": "paris_02.jpg",
39
+ "height": 350,
40
+ "imgpath": "images/",
41
+ "thumbheight": 56,
42
+ "thumbpath": "thumbnails/",
43
+ "width": 262
44
+ }
45
+ ]
46
+
47
+ === Installation
48
+
49
+ `sudo gem install csv2json --source gemcutter.org`
50
+
51
+ === Usage
52
+
53
+ Usage: csv2json [INPUT] [OPTIONS]
54
+
55
+ Specific options:
56
+ -o, --output FILE Write output to a file
57
+ -h, --help Show this message
58
+ -v, --version Show version
59
+
60
+ === Alternative usage
61
+
62
+ common usage is `csv2json file.csv > file.json`
63
+
64
+ csv2json should behave like proper unix command-line utility working with pipes, redirects, etc.
65
+
66
+ `cat file.csv | csv2json | gzip > file.json.gz`
67
+
68
+ === Usage as a library
69
+
70
+ with files
71
+
72
+ require 'csv2json'
73
+
74
+ File.open('input.csv', 'r') do |input|
75
+ File.open('output.json', 'w') do |output|
76
+ CSV2JSON.parse(input, output)
77
+ end
78
+ end
79
+
80
+ or in-memory
81
+
82
+ require 'csv2json'
83
+
84
+ input = StringIO.new(csv_string)
85
+ output = StringIO.new()
86
+ CSV2JSON.parse(input, output)
87
+
88
+ output.pos = 0
89
+ puts output.read
90
+
91
+ == Want to contribute?
92
+
93
+ * Fork the project.
94
+ * Make your feature addition or bug fix.
95
+ * Add tests for it. This is important so I don't break it in a
96
+ future version unintentionally.
97
+ * Commit, do not mess with rakefile, version, or history.
98
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
99
+ * Send me a pull request. Bonus points for topic branches.
100
+
101
+ == Copyright
102
+
103
+ Copyright (c) 2009 Antonin Hildebrand. See LICENSE for details.
104
+
105
+ Check out [http://binaryage.com](http://binaryage.com)
data/Rakefile ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require File.join(File.expand_path(File.dirname(__FILE__)), 'lib', 'csv2json.rb')
4
+
5
+ begin
6
+ require 'jeweler'
7
+ Jeweler::Tasks.new do |gem|
8
+ gem.version = CSV2JSON::VERSION
9
+ gem.name = "csv2json"
10
+ gem.summary = %Q{.csv to .json converter}
11
+ gem.description = %Q{handy for converting xls files to json}
12
+ gem.email = "antonin@hildebrand.cz"
13
+ gem.homepage = "http://github.com/darwin/csv2json"
14
+ gem.authors = ["Antonin Hildebrand"]
15
+ gem.add_development_dependency "shoulda", ">= 0"
16
+ # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
+ end
18
+ Jeweler::GemcutterTasks.new
19
+ rescue LoadError
20
+ puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
21
+ end
22
+
23
+ require 'rake/testtask'
24
+ Rake::TestTask.new(:test) do |test|
25
+ test.libs << 'lib' << 'test'
26
+ test.pattern = 'test/**/test_*.rb'
27
+ test.verbose = true
28
+ end
29
+
30
+ begin
31
+ require 'rcov/rcovtask'
32
+ Rcov::RcovTask.new do |test|
33
+ test.libs << 'test'
34
+ test.pattern = 'test/**/test_*.rb'
35
+ test.verbose = true
36
+ end
37
+ rescue LoadError
38
+ task :rcov do
39
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
+ end
41
+ end
42
+
43
+ task :test => :check_dependencies
44
+
45
+ task :default => :test
46
+
47
+ require 'rake/rdoctask'
48
+ Rake::RDocTask.new do |rdoc|
49
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
50
+
51
+ rdoc.rdoc_dir = 'rdoc'
52
+ rdoc.title = "csv2json #{version}"
53
+ rdoc.rdoc_files.include('README*')
54
+ rdoc.rdoc_files.include('lib/**/*.rb')
55
+ end
data/bin/csv2json ADDED
@@ -0,0 +1,61 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "rubygems"
4
+ require 'optparse'
5
+ require 'ostruct'
6
+ require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib', 'csv2json.rb') # this form is important for local development
7
+
8
+ module CSV2JSONRunner
9
+
10
+ # command-line parsing
11
+ COMMAND = File.basename($0)
12
+ USAGE = "Usage: #{COMMAND} [INPUT] [OPTIONS]"
13
+
14
+ options = OpenStruct.new
15
+ options.output = "-"
16
+
17
+ opts = OptionParser.new do |o|
18
+ o.banner = USAGE
19
+ o.separator ""
20
+ o.separator "Specific options:"
21
+
22
+ o.on("-o", "--output FILE", "Write output to a file") do |fn|
23
+ options.output = fn
24
+ end
25
+
26
+ o.on_tail("-h", "--help", "Show this message") do
27
+ puts o
28
+ exit
29
+ end
30
+
31
+ o.on_tail("-v", "--version", "Show version") do
32
+ puts CSV2JSON::VERSION
33
+ exit
34
+ end
35
+ end
36
+
37
+ begin
38
+ opts.parse!(ARGV)
39
+ rescue
40
+ die "Unable to parse options: #{$!}"
41
+ end
42
+
43
+ # initialize output handle
44
+ if options.output == "-"
45
+ OUT = $stdout.clone
46
+ else
47
+ OUT = File.open(options.output, "w")
48
+ end
49
+
50
+ if ARGV.size > 0
51
+ IN = File.open(ARGV[0], "r")
52
+ else
53
+ IN = StringIO.new($stdin.read) # cannot be just $stdin.clone because FasterCSV is seeking in file :-(
54
+ end
55
+
56
+ # run the command
57
+ CSV2JSON.parse(IN, OUT)
58
+
59
+ # leave in peace
60
+ OUT.flush
61
+ end
data/lib/csv2json.rb ADDED
@@ -0,0 +1,36 @@
1
+ require 'fastercsv'
2
+ require 'json'
3
+
4
+ module CSV2JSON
5
+ VERSION = "0.1.0"
6
+
7
+ # convert an input string value to integer or float if applicable
8
+ def convert(val)
9
+ return Integer(val) if val.to_i.to_s == val
10
+ Float(val) rescue val
11
+ end
12
+
13
+ # input and output are file objects, you can use StringIO if you want to work in memory
14
+ def parse(input, output, headers=nil)
15
+ result = Array.new
16
+
17
+ FasterCSV.new(input).each do |row|
18
+ # treat first row as headers if the caller didn't provide them
19
+ unless headers
20
+ headers = row
21
+ next
22
+ end
23
+
24
+ # build JSON snippet and append it to the result
25
+ snippet = Hash.new
26
+ headers.each_index { |i| snippet[headers[i]] = self.convert(row[i]) }
27
+ result << snippet
28
+ end
29
+
30
+ output << JSON.pretty_generate(result)
31
+ end
32
+
33
+ module_function :parse
34
+ module_function :convert
35
+
36
+ end
@@ -0,0 +1,16 @@
1
+ Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax
2
+ Headquarters,1600 Amphitheatre Parkway,,,Mountain View,CA,94043,650-253-0000,650-253-0001
3
+ New York Sales & Engineering Office,76 Ninth Avenue,,,New York,NY,10011,212-565-0000,212-565-0001
4
+ Ann Arbor Sales Office,201 South Division Street,,,Ann Arbor,MI,48104,734-332-6500,734-332-6501
5
+ Atlanta Sales & Engineering Office,10 10th Street NE,,,Atlanta,GA,30309,404-487-9000,404-487-9001
6
+ Boulder Sales & Engineering Office,2590 Pearl St.,,,Boulder,CO,80302,303-245-0086,303-535-5592
7
+ Cambridge Sales & Engineering Office,5 Cambridge Center,,,Cambridge,MA,02142,617-682-3635,617-249-0199
8
+ Chicago Sales & Engineering Office,20 West Kinzie St.,,,Chicago,IL,60610,312-840-4100,312-840-4101
9
+ Coppell Sales Office,701 Canyon Drive,,,Coppell,TX,75019,214-451-4000,214-451-4001
10
+ Detroit Sales Office,114 Willits Street,,,Birmingham,MI,48009,248-351-6220,248-351-6227
11
+ Irvine Sales & Engineering Office,19540 Jamboree Road,,,Irvine,CA,92612,949-794-1600,949-794-1601
12
+ Pittsburgh Engineering Office,4720 Forbes Avenue,,,Pittsburgh,PA,15213,,
13
+ Santa Monica Sales & Engineering Office,604 Arizona Avenue,,,Santa Monica,CA,90401,310-460-4000,310-309-6840
14
+ Seattle Engineering Office,720 4th Avenue,,,Kirkland,WA,98033,425-739-5600,425-739-5601
15
+ Seattle Sales Office,501 N. 34th Street,,,Seattle,WA,98103,206-876-1500,206-876-1501
16
+ Washington D.C. Public Policy Office,1001 Pennsylvania Avenue NW,,,Washington,DC,20004,202-742-6520,
@@ -0,0 +1,167 @@
1
+ [
2
+ {
3
+ "Address3": null,
4
+ "Zip": 94043,
5
+ "City": "Mountain View",
6
+ "Phone": "650-253-0000",
7
+ "Fax": "650-253-0001",
8
+ "State": "CA",
9
+ "Office": "Headquarters",
10
+ "Address1": "1600 Amphitheatre Parkway",
11
+ "Address2": null
12
+ },
13
+ {
14
+ "Address3": null,
15
+ "Zip": 10011,
16
+ "City": "New York",
17
+ "Phone": "212-565-0000",
18
+ "Fax": "212-565-0001",
19
+ "State": "NY",
20
+ "Office": "New York Sales & Engineering Office",
21
+ "Address1": "76 Ninth Avenue",
22
+ "Address2": null
23
+ },
24
+ {
25
+ "Address3": null,
26
+ "Zip": 48104,
27
+ "City": "Ann Arbor",
28
+ "Phone": "734-332-6500",
29
+ "Fax": "734-332-6501",
30
+ "State": "MI",
31
+ "Office": "Ann Arbor Sales Office",
32
+ "Address1": "201 South Division Street",
33
+ "Address2": null
34
+ },
35
+ {
36
+ "Address3": null,
37
+ "Zip": 30309,
38
+ "City": "Atlanta",
39
+ "Phone": "404-487-9000",
40
+ "Fax": "404-487-9001",
41
+ "State": "GA",
42
+ "Office": "Atlanta Sales & Engineering Office",
43
+ "Address1": "10 10th Street NE",
44
+ "Address2": null
45
+ },
46
+ {
47
+ "Address3": null,
48
+ "Zip": 80302,
49
+ "City": "Boulder",
50
+ "Phone": "303-245-0086",
51
+ "Fax": "303-535-5592",
52
+ "State": "CO",
53
+ "Office": "Boulder Sales & Engineering Office",
54
+ "Address1": "2590 Pearl St.",
55
+ "Address2": null
56
+ },
57
+ {
58
+ "Address3": null,
59
+ "Zip": 2142.0,
60
+ "City": "Cambridge",
61
+ "Phone": "617-682-3635",
62
+ "Fax": "617-249-0199",
63
+ "State": "MA",
64
+ "Office": "Cambridge Sales & Engineering Office",
65
+ "Address1": "5 Cambridge Center",
66
+ "Address2": null
67
+ },
68
+ {
69
+ "Address3": null,
70
+ "Zip": 60610,
71
+ "City": "Chicago",
72
+ "Phone": "312-840-4100",
73
+ "Fax": "312-840-4101",
74
+ "State": "IL",
75
+ "Office": "Chicago Sales & Engineering Office",
76
+ "Address1": "20 West Kinzie St.",
77
+ "Address2": null
78
+ },
79
+ {
80
+ "Address3": null,
81
+ "Zip": 75019,
82
+ "City": "Coppell",
83
+ "Phone": "214-451-4000",
84
+ "Fax": "214-451-4001",
85
+ "State": "TX",
86
+ "Office": "Coppell Sales Office",
87
+ "Address1": "701 Canyon Drive",
88
+ "Address2": null
89
+ },
90
+ {
91
+ "Address3": null,
92
+ "Zip": 48009,
93
+ "City": "Birmingham",
94
+ "Phone": "248-351-6220",
95
+ "Fax": "248-351-6227",
96
+ "State": "MI",
97
+ "Office": "Detroit Sales Office",
98
+ "Address1": "114 Willits Street",
99
+ "Address2": null
100
+ },
101
+ {
102
+ "Address3": null,
103
+ "Zip": 92612,
104
+ "City": "Irvine",
105
+ "Phone": "949-794-1600",
106
+ "Fax": "949-794-1601",
107
+ "State": "CA",
108
+ "Office": "Irvine Sales & Engineering Office",
109
+ "Address1": "19540 Jamboree Road",
110
+ "Address2": null
111
+ },
112
+ {
113
+ "Address3": null,
114
+ "Zip": 15213,
115
+ "City": "Pittsburgh",
116
+ "Phone": null,
117
+ "Fax": null,
118
+ "State": "PA",
119
+ "Office": "Pittsburgh Engineering Office",
120
+ "Address1": "4720 Forbes Avenue",
121
+ "Address2": null
122
+ },
123
+ {
124
+ "Address3": null,
125
+ "Zip": 90401,
126
+ "City": "Santa Monica",
127
+ "Phone": "310-460-4000",
128
+ "Fax": "310-309-6840",
129
+ "State": "CA",
130
+ "Office": "Santa Monica Sales & Engineering Office",
131
+ "Address1": "604 Arizona Avenue",
132
+ "Address2": null
133
+ },
134
+ {
135
+ "Address3": null,
136
+ "Zip": 98033,
137
+ "City": "Kirkland",
138
+ "Phone": "425-739-5600",
139
+ "Fax": "425-739-5601",
140
+ "State": "WA",
141
+ "Office": "Seattle Engineering Office",
142
+ "Address1": "720 4th Avenue",
143
+ "Address2": null
144
+ },
145
+ {
146
+ "Address3": null,
147
+ "Zip": 98103,
148
+ "City": "Seattle",
149
+ "Phone": "206-876-1500",
150
+ "Fax": "206-876-1501",
151
+ "State": "WA",
152
+ "Office": "Seattle Sales Office",
153
+ "Address1": "501 N. 34th Street",
154
+ "Address2": null
155
+ },
156
+ {
157
+ "Address3": null,
158
+ "Zip": 20004,
159
+ "City": "Washington",
160
+ "Phone": "202-742-6520",
161
+ "Fax": null,
162
+ "State": "DC",
163
+ "Office": "Washington D.C. Public Policy Office",
164
+ "Address1": "1001 Pennsylvania Avenue NW",
165
+ "Address2": null
166
+ }
167
+ ]