Permalink
Browse files

first version

  • Loading branch information...
darwin committed Dec 5, 2009
1 parent c858a96 commit 279e106dc926a23334ec47506843bee01b2181b0
View
@@ -0,0 +1,94 @@
+= csv2json
+
+Clients were sending me XLS files, but my webs consume JSON. So I needed to convert them to JSON easily from command-line.
+Tried to google for solution and surprisingly enough nothing solid existed.
+
+== Solution
+
+- export XLS as a CSV file (I use OpenOffice.org for this)
+- run `csv2json file.csv > file.json`
+- there is no step 3
+
+=== Sample
+
+note: make sure your XLS table has the first row with column names
+
+This CSV file:
+
+ thumbpath,imgpath,imgsrc,width,height,thumbsrc,thumbwidth,thumbheight
+ thumbnails/,images/,paris_01.jpg,350,262,paris_01.jpg,75,56
+ thumbnails/,images/,paris_02.jpg,262,350,paris_02.jpg,75,56
+
+gets turned into this JSON:
+
+ [
+ {
+ "thumbwidth": 75,
+ "imgsrc": "paris_01.jpg",
+ "thumbsrc": "paris_01.jpg",
+ "height": 262,
+ "imgpath": "images/",
+ "thumbheight": 56,
+ "thumbpath": "thumbnails/",
+ "width": 350
+ },
+ {
+ "thumbwidth": 75,
+ "imgsrc": "paris_02.jpg",
+ "thumbsrc": "paris_02.jpg",
+ "height": 350,
+ "imgpath": "images/",
+ "thumbheight": 56,
+ "thumbpath": "thumbnails/",
+ "width": 262
+ }
+ ]
+
+=== Installation
+
+`sudo gem install csv2json --source gemcutter.org`
+
+=== Alternative usage
+
+csv2json should behave like proper unix command-line utility working with pipes, redirects, etc.
+
+`cat file.csv | csv2json | gzip > file.json.gz`
+
+=== Usage as a library
+
+with files
+
+ require 'csv2json'
+
+ File.open('input.csv', 'r') do |input|
+ File.open('output.json', 'w') do |output|
+ CSV2JSON.parse(input, output)
+ end
+ end
+
+or in-memory
+
+ require 'csv2json'
+
+ input = StringIO.new(csv_string)
+ output = StringIO.new()
+ CSV2JSON.parse(input, output)
+
+ output.pos = 0
+ puts output.read
+
+== Want to contribute?
+
+* Fork the project.
+* Make your feature addition or bug fix.
+* Add tests for it. This is important so I don't break it in a
+ future version unintentionally.
+* Commit, do not mess with rakefile, version, or history.
+ (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)
+* Send me a pull request. Bonus points for topic branches.
+
+== Copyright
+
+Copyright (c) 2009 Antonin Hildebrand. See LICENSE for details.
+
+Check out [http://binaryage.com](http://binaryage.com)
View
@@ -1,17 +0,0 @@
-= csv2json
-
-Description goes here.
-
-== Note on Patches/Pull Requests
-
-* Fork the project.
-* Make your feature addition or bug fix.
-* Add tests for it. This is important so I don't break it in a
- future version unintentionally.
-* Commit, do not mess with rakefile, version, or history.
- (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)
-* Send me a pull request. Bonus points for topic branches.
-
-== Copyright
-
-Copyright (c) 2009 Antonin Hildebrand. See LICENSE for details.
View
@@ -10,7 +10,7 @@ begin
gem.email = "antonin@hildebrand.cz"
gem.homepage = "http://github.com/darwin/csv2json"
gem.authors = ["Antonin Hildebrand"]
- gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
+ gem.add_development_dependency "shoulda", ">= 0"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
View
@@ -0,0 +1,61 @@
+#!/usr/bin/env ruby
+
+require "rubygems"
+require 'optparse'
+require 'ostruct'
+require File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lib', 'csv2json.rb') # this form is important for local development
+
+module CSV2JSONRunner
+
+ # command-line parsing
+ COMMAND = File.basename($0)
+ USAGE = "Usage: #{COMMAND} [OPTIONS]"
+
+ options = OpenStruct.new
+ options.output = "-"
+
+ opts = OptionParser.new do |o|
+ o.banner = USAGE
+ o.separator ""
+ o.separator "Specific options:"
+
+ o.on("-o", "--output FILE", "Write output to a file") do |fn|
+ options.output = fn
+ end
+
+ o.on_tail("-h", "--help", "Show this message") do
+ puts o
+ exit
+ end
+
+ o.on_tail("-v", "--version", "Show version") do
+ puts "0.1.0" # TODO
+ exit
+ end
+ end
+
+ begin
+ opts.parse!(ARGV)
+ rescue
+ die "Unable to parse options: #{$!}"
+ end
+
+ # initialize output handle
+ if options.output == "-"
+ OUT = $stdout.clone
+ else
+ OUT = File.open(options.output, "w")
+ end
+
+ if ARGV.size > 0
+ IN = File.open(ARGV[0], "r")
+ else
+ IN = StringIO.new($stdin.read) # cannot be just $stdin.clone because FasterCSV is seeking in file :-(
+ end
+
+ # run the command
+ CSV2JSON.parse(IN, OUT)
+
+ # leave in peace
+ OUT.flush
+end
View
@@ -0,0 +1,35 @@
+require 'fastercsv'
+require 'json'
+
+module CSV2JSON
+
+ # convert an input string value to integer or float if applicable
+ def convert(val)
+ return Integer(val) if val.to_i.to_s == val
+ Float(val) rescue val
+ end
+
+ # input and output are file objects, you can use StringIO if you want to work in memory
+ def parse(input, output, headers=nil)
+ result = Array.new
+
+ FasterCSV.new(input).each do |row|
+ # treat first row as headers if the caller didn't provide them
+ unless headers
+ headers = row
+ next
+ end
+
+ # build JSON snippet and append it to the result
+ snippet = Hash.new
+ headers.each_index { |i| snippet[headers[i]] = self.convert(row[i]) }
+ result << snippet
+ end
+
+ output << JSON.pretty_generate(result)
+ end
+
+ module_function :parse
+ module_function :convert
+
+end
@@ -0,0 +1,16 @@
+Office,Address1,Address2,Address3,City,State,Zip,Phone,Fax
+Headquarters,1600 Amphitheatre Parkway,,,Mountain View,CA,94043,650-253-0000,650-253-0001
+New York Sales & Engineering Office,76 Ninth Avenue,,,New York,NY,10011,212-565-0000,212-565-0001
+Ann Arbor Sales Office,201 South Division Street,,,Ann Arbor,MI,48104,734-332-6500,734-332-6501
+Atlanta Sales & Engineering Office,10 10th Street NE,,,Atlanta,GA,30309,404-487-9000,404-487-9001
+Boulder Sales & Engineering Office,2590 Pearl St.,,,Boulder,CO,80302,303-245-0086,303-535-5592
+Cambridge Sales & Engineering Office,5 Cambridge Center,,,Cambridge,MA,02142,617-682-3635,617-249-0199
+Chicago Sales & Engineering Office,20 West Kinzie St.,,,Chicago,IL,60610,312-840-4100,312-840-4101
+Coppell Sales Office,701 Canyon Drive,,,Coppell,TX,75019,214-451-4000,214-451-4001
+Detroit Sales Office,114 Willits Street,,,Birmingham,MI,48009,248-351-6220,248-351-6227
+Irvine Sales & Engineering Office,19540 Jamboree Road,,,Irvine,CA,92612,949-794-1600,949-794-1601
+Pittsburgh Engineering Office,4720 Forbes Avenue,,,Pittsburgh,PA,15213,,
+Santa Monica Sales & Engineering Office,604 Arizona Avenue,,,Santa Monica,CA,90401,310-460-4000,310-309-6840
+Seattle Engineering Office,720 4th Avenue,,,Kirkland,WA,98033,425-739-5600,425-739-5601
+Seattle Sales Office,501 N. 34th Street,,,Seattle,WA,98103,206-876-1500,206-876-1501
+Washington D.C. Public Policy Office,1001 Pennsylvania Avenue NW,,,Washington,DC,20004,202-742-6520,
Oops, something went wrong.

0 comments on commit 279e106

Please sign in to comment.