Merge tag 'csv2edn-0.1.4'

This commit is contained in:
Simon Brooke 2020-01-27 13:30:16 +00:00
commit 1f3dc8aae9
4 changed files with 63 additions and 41 deletions

View file

@ -8,65 +8,67 @@ Simple command line utility to convert CSV files to EDN. Assumes the first row o
### Leiningen/Boot ### Leiningen/Boot
[csv2edn "0.1.0"] [csv2edn "0.1.4"]
### Clojure CLI/deps.edn ### Clojure CLI/deps.edn
csv2edn {:mvn/version "0.1.0"} csv2edn {:mvn/version "0.1.4"}
### Gradle ### Gradle
compile 'csv2edn:csv2edn:0.1.0' compile 'csv2edn:csv2edn:0.1.4'
### Maven ### Maven
<dependency> <dependency>
<groupId>csv2edn</groupId> <groupId>csv2edn</groupId>
<artifactId>csv2edn</artifactId> <artifactId>csv2edn</artifactId>
<version>0.1.0</version> <version>0.1.4</version>
</dependency> </dependency>
## Usage: as a standalone commandline tool ## Usage: as a standalone commandline tool
To run from the command line: To run from the command line:
$ java -jar csv2edn-0.1.0-standalone.jar [options] $ java -jar csv2edn-0.1.4-standalone.jar [options]
### Options ### Options
Where options are: Where options are:
-h, --help Print this message and exit. -f, --format FORMAT :edn Format the ouput as `FORMAT`
-i, --input INPUT The path name of the CSV file to be read. (expected to be either `edn` or `json`, defaults to `edn`)
-h, --help Print this message and exit.
-i, --input INPUT The path name of the CSV file to be read.
If no input file is specified, input will be read from standard input. If no input file is specified, input will be read from standard input.
-o, --output OUTPUT The path name of the EDN file to be written. -o, --output OUTPUT The path name of the EDN file to be written.
If no output file is specified, output will be written to standard output. If no output file is specified, output will be written to standard output.
-s, --separator SEPARATOR The character to treat as a separator in the -s, --separator SEPARATOR , The character to treat as a separator in
CSV file. If not specified, comma will be used by default. the CSV file
### Examples ### Examples
The simplest possible use is to simply use this in a pipeline: The simplest possible use is to simply use this in a pipeline:
$ cat path/to/file.csv |\ $ cat path/to/file.csv |\
java -jar csv2edn-0.1.0-standalone.jar > path/to/file.edn java -jar csv2edn-0.1.4-standalone.jar > path/to/file.edn
Exactly the same behaviour can be achieved by specifying input and output Exactly the same behaviour can be achieved by specifying input and output
paths: paths:
$ java -jar csv2edn-0.1.0-standalone.jar \ $ java -jar csv2edn-0.1.4-standalone.jar \
-i path/to/file.csv -o path/to/file.edn -i path/to/file.csv -o path/to/file.edn
or or
$ java -jar csv2edn-0.1.0-standalone.jar \ $ java -jar csv2edn-0.1.4-standalone.jar \
--input path/to/file.csv --output path/to/file.edn --input path/to/file.csv --output path/to/file.edn
## Usage: as a library ## Usage: as a library
To use this package as a library in your own code: To use this package as a library in your own code:
(:require [csv2edn.csv2edn :refer [csv->edn *options*]]) (:require [csv2edn.csv2edn :refer [csv->edn csv->json *options*]])
And then pass either filenames or a reader and writer respectively to the And then pass either filenames or a reader and writer respectively to the
function `cvs->edn`, thus: function `cvs->edn`, thus:
@ -95,6 +97,8 @@ Or else pass the separator character you want to use as a third argument:
(cvs->edn "path/to/data.csv" "path/to/data.edn" \|) (cvs->edn "path/to/data.csv" "path/to/data.edn" \|)
If you wish to produce JSON, call the function `csv->json` exactly as
`csv->edn` called above.
### Bugs ### Bugs

View file

@ -1,10 +1,11 @@
(defproject csv2edn "0.1.3" (defproject csv2edn "0.1.4"
:description "Simple command line utility to convert CSV files to EDN." :description "Simple command line utility to convert CSV files to EDN."
:url "https://github.com/simon-brooke/csv2edn" :url "https://github.com/simon-brooke/csv2edn"
:license {:name "GPL-2.0-or-later WITH Classpath-exception-2.0" :license {:name "GPL-2.0-or-later WITH Classpath-exception-2.0"
:url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"} :url "https://www.gnu.org/licenses/old-licenses/gpl-2.0.en.html"}
:dependencies [[org.clojure/clojure "1.8.0"] :dependencies [[org.clojure/clojure "1.8.0"]
[org.clojure/data.csv "0.1.4"] [org.clojure/data.csv "0.1.4"]
[org.clojure/data.json "0.2.7"]
[org.clojure/tools.cli "0.4.2"]] [org.clojure/tools.cli "0.4.2"]]
:main ^:skip-aot csv2edn.core :main ^:skip-aot csv2edn.core
:target-path "target/%s" :target-path "target/%s"

View file

@ -3,13 +3,18 @@
csv2edn.core csv2edn.core
(:require [clojure.java.io :as io] (:require [clojure.java.io :as io]
[clojure.tools.cli :refer [parse-opts]] [clojure.tools.cli :refer [parse-opts]]
[csv2edn.csv2edn :refer [csv->edn *options*]]) [csv2edn.csv2edn :refer [csv->edn csv->json *options*]])
(:gen-class)) (:gen-class))
(def cli-options (def cli-options
"Command line argument specification." "Command line argument specification."
[["-h" "--help" "Print this message and exit."] [["-f" "--format FORMAT" "Format the ouput as `FORMAT`
(expected to be either `edn` or `json`, defaults to `edn`)"
:default :edn
:parse-fn #(keyword %)
:validate [#(#{:edn :json} %) "Format should be one of `edn`, `json`."]]
["-h" "--help" "Print this message and exit."]
["-i" "--input INPUT" "The path name of the CSV file to be read. ["-i" "--input INPUT" "The path name of the CSV file to be read.
If no input file is specified, input will be read from standard input." If no input file is specified, input will be read from standard input."
:validate [#(and :validate [#(and
@ -19,7 +24,8 @@
["-o" "--output OUTPUT" "The path name of the EDN file to be written. ["-o" "--output OUTPUT" "The path name of the EDN file to be written.
If no output file is specified, output will be written to standard output."] If no output file is specified, output will be written to standard output."]
["-s" "--separator SEPARATOR" ["-s" "--separator SEPARATOR"
"The character to treat as a separator in the CSV file" "The character to treat as a separator in
the CSV file"
:parse-fn #(first (str %)) :parse-fn #(first (str %))
:default \,] :default \,]
]) ])
@ -37,11 +43,9 @@
(apply str (interpose "; " (:errors args))) "")) (apply str (interpose "; " (:errors args))) ""))
(if-not (or (:errors args) (:help (:options args))) (if-not (or (:errors args) (:help (:options args)))
(binding [*options* (:options args)] (binding [*options* (:options args)]
(doall (let [from (or (:input *options*) (io/reader *in*))
(csv->edn to (or (:output *options*) (io/writer *out*))]
(or (case (:format *options*)
(:input *options*) :json (doall (csv->json from to))
(io/reader *in*)) :edn (doall (csv->edn from to) )))))))
(or (:output *options*) (io/writer *out*)))
)))))

View file

@ -1,6 +1,7 @@
(ns ^{:doc "Conversion from CVS to EDN." (ns ^{:doc "Conversion from CVS to EDN."
:author "Simon Brooke"} csv2edn.csv2edn :author "Simon Brooke"} csv2edn.csv2edn
(:require [clojure.data.csv :as csv] (:require [clojure.data.csv :as csv]
[clojure.data.json :as json]
[clojure.java.io :as io] [clojure.java.io :as io]
[clojure.pprint :refer [pprint]] [clojure.pprint :refer [pprint]]
[clojure.string :refer [lower-case]])) [clojure.string :refer [lower-case]]))
@ -27,20 +28,32 @@
([from] (csv->edn from nil)) ([from] (csv->edn from nil))
([from to] (csv->edn from to (:separator *options*))) ([from to] (csv->edn from to (:separator *options*)))
([from to sep] ([from to sep]
(let [data (with-open [reader (if (string? from)(io/reader from) from)] (let [data (with-open [reader (if (string? from)(io/reader from) from)]
(doall (doall
(csv/read-csv (csv/read-csv
reader reader
:separator (first (str sep))))) :separator (first (str sep)))))
headers (map #(keyword (lower-case %)) (first data))] headers (map #(keyword (lower-case %)) (first data))
(let [result (map result (map
#(zipmap headers (map maybe-read %)) #(zipmap headers (map maybe-read %))
(rest data))] (rest data))]
(if to (if to
(with-open [writer (if (string? to) (io/writer to) to)] (with-open [writer (if (string? to) (io/writer to) to)]
(pprint (pprint
result result
writer))) writer)))
result)))) result)))
(defn csv->json
"Read a CSV stream from the reader or filename `from`, and write corresponding
JSON to the reader or filname `to`, using the separator character `sep`. Assume
column headers are in row 1. If `from` is `nil` or not supplied, do not write.
It `sep` is not supplied, take the `:separator` value from `*options*`. Returns
a (possibly-lazy) sequence of maps."
([from] (csv->json from nil))
([from to] (csv->json from to (:separator *options*)))
([from to sep]
(let [result (json/write-str (csv->edn from nil sep))]
(if to
(spit to result))
result)))