Skip to content

Commit

Permalink
Custom IO in and IO out
Browse files Browse the repository at this point in the history
  • Loading branch information
silasb committed Aug 14, 2018
1 parent c4eb745 commit d74317a
Show file tree
Hide file tree
Showing 3 changed files with 75 additions and 10 deletions.
4 changes: 3 additions & 1 deletion bin/cli.cr
Expand Up @@ -80,7 +80,9 @@ class CLI < Admiral::Command

options[:empty_value_replace_char] = flags.empty_value_replace_char

Csv::To::Json.run(io, options)
out_io = STDOUT

Csv::To::Json.run(io, out_io, options)
end
end

Expand Down
62 changes: 62 additions & 0 deletions spec/csv-to-json_spec.cr
Expand Up @@ -20,5 +20,67 @@ describe Csv::To::Json do
it "will respond to #run" do
Csv::To::Json.responds_to?(:run).should be_true
end

context "with io object" do
it "will try to parse the CSV object and output to out_io" do
in_io = IO::Memory.new("field 1,field 2\nvalue 1,\n")
out_io = IO::Memory.new()

Csv::To::Json.run(in_io, out_io)

out_io.seek(0)
out_io.to_s.should contain("[\n{\"field 1\":\"value 1\",\"field 2\":\"\"}\n]\n")
end
end

context "with options" do
context "with empty_value_replace_char option" do
it "will replace each empty value with the empty_value_replace_char char" do
in_io = IO::Memory.new("field 1,field 2\nvalue 1,\n")
out_io = IO::Memory.new()

options = {
:empty_value_replace_char => "blah"
}

Csv::To::Json.run(in_io, out_io, options)

out_io.seek(0)
out_io.to_s.should contain("blah")
end
end

context "with delimiter option" do
it "will parse on different delimiter" do
in_io = IO::Memory.new("field 1\tfield 2\nvalue 1\t\n")
out_io = IO::Memory.new()

options = {
:delimiter => '\t'
}

Csv::To::Json.run(in_io, out_io, options)

out_io.seek(0)
out_io.to_s.should contain("[\n{\"field 1\":\"value 1\",\"field 2\":\"\"}\n]\n")
end
end

context "with quote_char option" do
it "will parse on different quote char" do
in_io = IO::Memory.new("field 1,!\"field 2\"!\nvalue 1,\n")
out_io = IO::Memory.new()

options = {
:quote_char => '!'
}

Csv::To::Json.run(in_io, out_io, options)

out_io.seek(0)
out_io.to_s.should contain("[\n{\"field 1\":\"value 1\",\"\\\"field 2\\\"\":\"\"}\n]\n")
end
end
end
end
end
19 changes: 10 additions & 9 deletions src/csv-to-json.cr
Expand Up @@ -3,20 +3,21 @@ require "csv"
require "json"

module Csv::To::Json
def self.run(io, options = {} of Symbol => String)
# Processes a CSV file on *in_io* with *options* and produces a JSON object on *out_io*
def self.run(in_io, out_io, options = {} of Symbol => String)
STDIN.blocking = true

empty_value_replace_char = options[:empty_value_replace_char]
empty_value_replace_char = options.fetch(:empty_value_replace_char, "").as(String)
tail = options.delete :tail
delimiter = options.fetch(:delimiter, ',').as(Char)
quote_char = options.fetch(:quote_char, '"').as(Char)

#file = File.open(csv)
csv_io = CSV::Parser.new(io, delimiter, quote_char)
csv_io = CSV::Parser.new(in_io, delimiter, quote_char)

header = csv_io.next_row

puts "["
out_io.puts "["

count = 0
row = csv_io.next_row
Expand All @@ -43,7 +44,7 @@ module Csv::To::Json
}
end

print Hash.zip(
out_io.print Hash.zip(
header.as(Array(String)),
values
).to_json
Expand All @@ -54,21 +55,21 @@ module Csv::To::Json
STDERR.puts "\n"
STDERR.puts "#{ex} at line: #{count + 3}"

io.seek(-1 * ex.column_number, IO::Seek::Current)
STDERR.puts io.read_line
in_io.seek(-1 * ex.column_number, IO::Seek::Current)
STDERR.puts in_io.read_line

exit 2
end

# super ugly
if tail.nil? ? !row.nil? : tail.to_i != count + 1 && !row.nil?
puts ","
out_io.puts ","
else
break
end
count += 1
end

puts "\n]"
out_io.puts "\n]"
end
end

0 comments on commit d74317a

Please sign in to comment.