From 2f2b0140277b35016cdefb01b6652004ddca5873 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Thu, 9 Feb 2017 18:48:36 -0700 Subject: [PATCH 01/33] stub of command-line js-only version of index.html --- json2csv.js | 278 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 278 insertions(+) create mode 100644 json2csv.js diff --git a/json2csv.js b/json2csv.js new file mode 100644 index 0000000..3df437c --- /dev/null +++ b/json2csv.js @@ -0,0 +1,278 @@ + var excerptRows = 7; + var input; + var url; + var lastSaved; + + // function log(msg) { + // return $(".console").removeClass("error").html(msg); + // } + + // function error(msg) { + // return log(msg).addClass("error"); + // } + + function doJSON() { + // just in case + $(".drop").hide(); + + // get input JSON, try to parse it + var newInput = $(".json textarea").val(); + if (newInput == input) return; + + input = newInput; + if (!input) { + // wipe the rendered version too + $(".json code").html(""); + return; + } + + var json = jsonFrom(input); + + // if succeeded, prettify and highlight it + // highlight shows when textarea loses focus + if (json) { + // Reset any error message from previous failed parses. + $("div.error").hide(); + $("div.warning").show(); + + var pretty = JSON.stringify(json, undefined, 2); + $(".json code").html(pretty); + if (pretty.length < (50 * 1024)) + hljs.highlightBlock($(".json code").get(0)); + + // convert to CSV, make available + doCSV(json); + } else { + // Show error. + $("div.warning").hide(); + $("div.error").show(); + $(".json code").html(""); + } + + // Either way, update the error-reporting link to include the latest. + setErrorReporting(null, input); + + return true; + } + + // show rendered JSON + function showJSON(rendered) { + console.log("ordered to show JSON: " + rendered); + if (rendered) { + if ($(".json code").html()) { + console.log("there's code to show, showing..."); + $(".json .rendered").show(); + $(".json .editing").hide(); + } + } else { + $(".json .rendered").hide(); + $(".json .editing").show().focus(); + } + } + + function showCSV(rendered) { + if (rendered) { + if ($(".csv table").html()) { + $(".csv .rendered").show(); + $(".csv .editing").hide(); + } + } else { + $(".csv .rendered").hide(); + $(".csv .editing").show().focus(); + } + } + + // takes an array of flat JSON objects, converts them to arrays + // renders them into a small table as an example + function renderCSV(objects) { + var rows = $.csv.fromObjects(objects, {justArrays: true}); + if (rows.length < 1) return; + + // find CSV table + var table = $(".csv table")[0]; + $(table).html(""); + + // render header row + var thead = document.createElement("thead"); + var tr = document.createElement("tr"); + var header = rows[0]; + for (field in header) { + var th = document.createElement("th"); + $(th).html(header[field]) + tr.appendChild(th); + } + thead.appendChild(tr); + + // render body of table + var tbody = document.createElement("tbody"); + for (var i=1; i Date: Thu, 9 Feb 2017 18:49:33 -0700 Subject: [PATCH 02/33] Update README.md --- README.md | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/README.md b/README.md index 2abee8d..4329ef5 100644 --- a/README.md +++ b/README.md @@ -2,19 +2,4 @@ A simple JSON to CSV converter that handles objects and nested documents. -Conversion happens inside the browser, in straight JavaScript. It may choke on large files. - -Please file all bugs [in the issue tracker](https://github.com/konklone/json/issues). - -Read more about the converter and why I built it: "[Making JSON as simple as a spreadsheet](http://sunlightfoundation.com/blog/2014/03/11/making-json-as-simple-as-a-spreadsheet/)". - - -## Public domain - -This project makes uses of certain externally licensed works, including (but not limited to) Bootstrap, Highlight.js, jQuery and jquery-csv. Any such works retain their original license, even if they have been subsequently modified by me. - -All **other files** in this project are [dedicated to the public domain](LICENSE). As spelled out in [CONTRIBUTING](CONTRIBUTING.md): - -> The project is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](http://creativecommons.org/publicdomain/zero/1.0/). - -> All contributions to this project will be released under the CC0 dedication. By submitting a pull request, you are agreeing to comply with this waiver of copyright interest. \ No newline at end of file +Previously a browser-side tool; attempting to turn it into a command line tool. Based on https://github.com/konklone/json. From e27786953c9a053c02fccc739bc023118a74e139 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Thu, 9 Feb 2017 19:07:03 -0700 Subject: [PATCH 03/33] basic skeleton: reads in a json file and prints it stringified --- json2csv.js | 561 +++++++++++++++++++++++++++------------------------- 1 file changed, 294 insertions(+), 267 deletions(-) diff --git a/json2csv.js b/json2csv.js index 3df437c..b7ed8da 100644 --- a/json2csv.js +++ b/json2csv.js @@ -1,278 +1,305 @@ - var excerptRows = 7; - var input; - var url; - var lastSaved; - - // function log(msg) { - // return $(".console").removeClass("error").html(msg); - // } - - // function error(msg) { - // return log(msg).addClass("error"); - // } - - function doJSON() { - // just in case - $(".drop").hide(); - - // get input JSON, try to parse it - var newInput = $(".json textarea").val(); - if (newInput == input) return; - - input = newInput; - if (!input) { - // wipe the rendered version too - $(".json code").html(""); - return; - } - - var json = jsonFrom(input); - - // if succeeded, prettify and highlight it - // highlight shows when textarea loses focus - if (json) { - // Reset any error message from previous failed parses. - $("div.error").hide(); - $("div.warning").show(); - - var pretty = JSON.stringify(json, undefined, 2); - $(".json code").html(pretty); - if (pretty.length < (50 * 1024)) - hljs.highlightBlock($(".json code").get(0)); - - // convert to CSV, make available - doCSV(json); - } else { - // Show error. - $("div.warning").hide(); - $("div.error").show(); - $(".json code").html(""); - } - - // Either way, update the error-reporting link to include the latest. - setErrorReporting(null, input); - - return true; - } - - // show rendered JSON - function showJSON(rendered) { - console.log("ordered to show JSON: " + rendered); - if (rendered) { - if ($(".json code").html()) { - console.log("there's code to show, showing..."); - $(".json .rendered").show(); - $(".json .editing").hide(); - } - } else { - $(".json .rendered").hide(); - $(".json .editing").show().focus(); - } - } - - function showCSV(rendered) { - if (rendered) { - if ($(".csv table").html()) { - $(".csv .rendered").show(); - $(".csv .editing").hide(); - } - } else { - $(".csv .rendered").hide(); - $(".csv .editing").show().focus(); - } - } - - // takes an array of flat JSON objects, converts them to arrays - // renders them into a small table as an example - function renderCSV(objects) { - var rows = $.csv.fromObjects(objects, {justArrays: true}); - if (rows.length < 1) return; - - // find CSV table - var table = $(".csv table")[0]; - $(table).html(""); - - // render header row - var thead = document.createElement("thead"); - var tr = document.createElement("tr"); - var header = rows[0]; - for (field in header) { - var th = document.createElement("th"); - $(th).html(header[field]) - tr.appendChild(th); - } - thead.appendChild(tr); - - // render body of table - var tbody = document.createElement("tbody"); - for (var i=1; i 0) { + usage( ); + process.exit(0) } - - // loads original pasted JSON from textarea, saves to anonymous gist - // rate-limiting means this could easily fail with a 403. - function saveJSON() { - if (!input) return false; - if (input == lastSaved) return false; - - // save a permalink to an anonymous gist - var gist = { - description: "test", - public: false, - files: { - "source.json": { - "content": input - } - } - }; - - // TODO: show spinner/msg while this happens - - console.log("Saving to an anonymous gist..."); - $.post( - 'https://api.github.com/gists', - JSON.stringify(gist) - ).done(function(data, status, xhr) { - - // take new Gist id, make permalink - setPermalink(data.id); - - // send analytics event - Events.permalink(); - - // mark what we last saved - lastSaved = input; - - // update error-reporting link, including permalink - setErrorReporting(data.id, input); - - console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); - - }).fail(function(xhr, status, errorThrown) { - console.log(xhr); - - // send analytics event - Events.permalink_error(status); - - // TODO: gracefully handle rate limit errors - // if (status == 403) - - // TODO: show when saving will be available - // e.g. "try again in 5 minutes" - // var reset = xhr.getResponseHeader("X-RateLimit-Reset"); - // var date = new Date(); - // date.setTime(parseInt(reset) * 1000); - // use http://momentjs.com/ to say "in _ minutes" - - }); - - return false; - } - - // Updates the error-reporting link to include current details. - // - // If the passed-in `id` is not null, a permalink is included. - // If the passed-in `id` is null, then no permalink is included. - // (Needed explicitly because the current URL doesn't always refer - // to a permalink related to the current value of the textarea.) - // - // The current body of the textarea will be encoded into the URI, - // to pre-populate the GitHub issue template, but only if the body - // is < 7KB (7,168). GitHub's nginx server rejects query strings - // longer than ~8KB. - // - // If no `id` is given, and content is too long, the URL will - // encode only a title, and no body. - function setErrorReporting(id, content) { - var base = "https://github.com/konklone/json/issues/new"; - - var title = "Error parsing some specific JSON"; - - var body = "I'm having an issue converting this JSON:\n\n"; - if (id) body += ( - window.location.protocol + "//" + - window.location.host + window.location.pathname + - "?id=" + id + "\n\n" - ); - - if (content.length <= (7 * 1024)) - body += ("```json\n" + content + "\n```"); - - var finalUrl = base + "?title=" + encodeURIComponent(title) + - "&body=" + encodeURIComponent(body); - - $(".error a.report").attr("href", finalUrl); - - // console.log("Updated error reporting link to:" + finalUrl); - return true; + if (!inputFileName) { + usage( ) + process.exit(1); } - // given a valid gist ID, set the permalink to use it - function setPermalink(id) { - if (history && history.pushState) - history.pushState({id: id}, null, "?id=" + id); - - // log("Permalink created! (Copy from the location bar.)") + var fs = require('fs'); + var cwd = process.cwd() + try { + var inputData = JSON.parse(fs.readFileSync(inputFileName, 'utf8')); + } catch (e) { + return console.error("Could not parse input file: ", e); } - // check query string for gist ID - function loadPermalink() { - var id = getParam("id"); - if (!id) return; - - $.get('https://api.github.com/gists/' + id, - function(data, status, xhr) { - console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); - - var input = data.files["source.json"].content; - $(".json textarea").val(input); - doJSON(); - showJSON(true); - } - ).fail(function(xhr, status, errorThrown) { - console.log("Error fetching anonymous gist!"); - console.log(xhr); - console.log(status); - console.log(errorThrown); - }); - } + console.error(JSON.stringify(inputData)); +} + +function doJSON() { + // just in case + $(".drop").hide(); + + // get input JSON, try to parse it + var newInput = $(".json textarea").val(); + if (newInput == input) return; + + input = newInput; + if (!input) { + // wipe the rendered version too + $(".json code").html(""); + return; + } + + var json = jsonFrom(input); + + // if succeeded, prettify and highlight it + // highlight shows when textarea loses focus + if (json) { + // Reset any error message from previous failed parses. + $("div.error").hide(); + $("div.warning").show(); + + var pretty = JSON.stringify(json, undefined, 2); + $(".json code").html(pretty); + if (pretty.length < (50 * 1024)) + hljs.highlightBlock($(".json code").get(0)); + + // convert to CSV, make available + doCSV(json); + } else { + // Show error. + $("div.warning").hide(); + $("div.error").show(); + $(".json code").html(""); + } + + // Either way, update the error-reporting link to include the latest. + setErrorReporting(null, input); + + return true; +} + +// show rendered JSON +function showJSON(rendered) { + console.log("ordered to show JSON: " + rendered); + if (rendered) { + if ($(".json code").html()) { + console.log("there's code to show, showing..."); + $(".json .rendered").show(); + $(".json .editing").hide(); + } + } else { + $(".json .rendered").hide(); + $(".json .editing").show().focus(); + } +} + +function showCSV(rendered) { + if (rendered) { + if ($(".csv table").html()) { + $(".csv .rendered").show(); + $(".csv .editing").hide(); + } + } else { + $(".csv .rendered").hide(); + $(".csv .editing").show().focus(); + } +} + +// takes an array of flat JSON objects, converts them to arrays +// renders them into a small table as an example +function renderCSV(objects) { + var rows = $.csv.fromObjects(objects, {justArrays: true}); + if (rows.length < 1) return; + + // find CSV table + var table = $(".csv table")[0]; + $(table).html(""); + + // render header row + var thead = document.createElement("thead"); + var tr = document.createElement("tr"); + var header = rows[0]; + for (field in header) { + var th = document.createElement("th"); + $(th).html(header[field]) + tr.appendChild(th); + } + thead.appendChild(tr); + + // render body of table + var tbody = document.createElement("tbody"); + for (var i=1; i Date: Thu, 9 Feb 2017 19:19:18 -0700 Subject: [PATCH 04/33] call doCSV, minus the html bits --- json2csv.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/json2csv.js b/json2csv.js index b7ed8da..2357826 100644 --- a/json2csv.js +++ b/json2csv.js @@ -36,6 +36,7 @@ if (!module.parent) { } console.error(JSON.stringify(inputData)); + doCSV(inputData); } function doJSON() { @@ -158,7 +159,7 @@ function doCSV(json) { for (var row in inArray) outArray[outArray.length] = parse_object(inArray[row]); - $("span.rows.count").text("" + outArray.length); + //$("span.rows.count").text("" + outArray.length); var csv = $.csv.fromObjects(outArray); // excerpt and render first 10 rows @@ -166,13 +167,13 @@ function doCSV(json) { showCSV(true); // show raw data if people really want it - $(".csv textarea").val(csv); + //$(".csv textarea").val(csv); // download link to entire CSV as data // thanks to https://jsfiddle.net/terryyounghk/KPEGU/ // and https://stackoverflow.com/questions/14964035/how-to-export-javascript-array-info-to-csv-on-client-side - var uri = "data:text/csv;charset=utf-8," + encodeURIComponent(csv); - $(".csv a.download").attr("href", uri); + //var uri = "data:text/csv;charset=utf-8," + encodeURIComponent(csv); + //$(".csv a.download").attr("href", uri); } // loads original pasted JSON from textarea, saves to anonymous gist From 365f28936df95b65401e6e07f1a1d638ab794584 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Thu, 9 Feb 2017 19:30:31 -0700 Subject: [PATCH 05/33] require stuff --- json2csv.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/json2csv.js b/json2csv.js index 2357826..55fb243 100644 --- a/json2csv.js +++ b/json2csv.js @@ -15,6 +15,9 @@ function usage ( ) { console.log('usage: ', process.argv.slice(0, 2), 'inputfile.json'); } +require('./assets/jquery-2.1.1.min.js')(); +require('./assets/jquery.csv.js')(); +require('./assets/site.js')(); if (!module.parent) { var inputFileName = process.argv.slice(2, 3).pop(); From 896e1b4bdb68c84cda583868b6cacb3fc4698c6b Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 11 Feb 2017 18:31:48 -0800 Subject: [PATCH 06/33] convert functions to node-compatible form --- assets/site.js | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/assets/site.js b/assets/site.js index f823028..f1fdf88 100644 --- a/assets/site.js +++ b/assets/site.js @@ -13,7 +13,7 @@ Events = { } -function getParam(name) { +getParam = function(name) { name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]"); var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"), results = regex.exec(location.search); @@ -25,7 +25,7 @@ function getParam(name) { // depends on jquery and jquery-csv (for now) -function parse_object(obj, path) { +parse_object = function(obj, path) { if (path == undefined) path = ""; @@ -56,8 +56,9 @@ function parse_object(obj, path) { // otherwise, just find the first one -function arrayFrom(json) { +arrayFrom = function(json) { var queue = [], next = json; + while (next !== undefined) { if ($.type(next) == "array") { @@ -82,11 +83,11 @@ function arrayFrom(json) { // adapted from Mattias Petter Johanssen: // https://www.quora.com/How-can-I-parse-unquoted-JSON-with-JavaScript/answer/Mattias-Petter-Johansson -function quoteKeys(input) { +quoteKeys = function(input) { return input.replace(/(['"])?([a-zA-Z0-9_]+)(['"])?:/g, '"$2": '); } -function removeTrailingComma(input) { +removeTrailingComma = function(input) { if (input.slice(-1) == ",") return input.slice(0,-1); else @@ -96,19 +97,19 @@ function removeTrailingComma(input) { // Rudimentary, imperfect detection of JSON Lines (http://jsonlines.org): // // Is there a closing brace and an opening brace with only whitespace between? -function isJSONLines(string) { +isJSONLines = function(string) { return !!(string.match(/\}\s+\{/)) } // To convert JSON Lines to JSON: // * Add a comma between spaced braces // * Surround with array brackets -function linesToJSON(string) { +linesToJSON = function(string) { return "[" + string.replace(/\}\s+\{/g, "}, {") + "]"; } // todo: add graceful error handling -function jsonFrom(input) { +jsonFrom = function(input) { var string = $.trim(input); if (!string) return; @@ -154,4 +155,4 @@ function jsonFrom(input) { console.log("Nope: that didn't work either. No good.") return result; -} \ No newline at end of file +} From 1c0afa6c80b479394077422f8b4dd822b667eddd Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 11 Feb 2017 18:34:32 -0800 Subject: [PATCH 07/33] make everything work --- json2csv.js | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/json2csv.js b/json2csv.js index 55fb243..65ace3b 100644 --- a/json2csv.js +++ b/json2csv.js @@ -15,10 +15,15 @@ function usage ( ) { console.log('usage: ', process.argv.slice(0, 2), 'inputfile.json'); } -require('./assets/jquery-2.1.1.min.js')(); -require('./assets/jquery.csv.js')(); -require('./assets/site.js')(); if (!module.parent) { + + var jsdom = require("jsdom").jsdom; + global.window = jsdom().defaultView; + global.jQuery = global.$ = require("jquery"); + + require('./assets/jquery-2.1.1.min.js'); + require('./assets/jquery.csv.js'); + require('./assets/site.js'); var inputFileName = process.argv.slice(2, 3).pop(); if ([null, '--help', '-h', 'help'].indexOf(inputFileName) > 0) { @@ -38,7 +43,7 @@ if (!module.parent) { return console.error("Could not parse input file: ", e); } - console.error(JSON.stringify(inputData)); + //console.error(JSON.stringify(inputData)); doCSV(inputData); } @@ -165,8 +170,9 @@ function doCSV(json) { //$("span.rows.count").text("" + outArray.length); var csv = $.csv.fromObjects(outArray); + console.log(csv); // excerpt and render first 10 rows - renderCSV(outArray.slice(0, excerptRows)); + //renderCSV(outArray.slice(0, excerptRows)); showCSV(true); // show raw data if people really want it From 799225e70c8741e91d00521db0464d02a113a2bd Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 11 Feb 2017 20:52:18 -0800 Subject: [PATCH 08/33] print inputData.length first --- json2csv.js | 1 + 1 file changed, 1 insertion(+) diff --git a/json2csv.js b/json2csv.js index 65ace3b..bac8151 100644 --- a/json2csv.js +++ b/json2csv.js @@ -44,6 +44,7 @@ if (!module.parent) { } //console.error(JSON.stringify(inputData)); + console.error("About to convert",inputData.length,"records to CSV"); doCSV(inputData); } From 0171d7e2903f37acf3faaf2e42ee741ab72fd613 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 11 Feb 2017 21:00:06 -0800 Subject: [PATCH 09/33] try splitting data into 100k-record chunks --- json2csv.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/json2csv.js b/json2csv.js index bac8151..9537bae 100644 --- a/json2csv.js +++ b/json2csv.js @@ -44,7 +44,13 @@ if (!module.parent) { } //console.error(JSON.stringify(inputData)); - console.error("About to convert",inputData.length,"records to CSV"); + var chunklength = 100000; + while(inputData.length > chunklength) { + var bigchunk = inputData.splice(0, chunklength-1) + console.error("About to convert chunk of",bigchunk.length,"records to CSV"); + doCSV(bigchunk); + } + console.error("About to convert remaining",inputData.length,"records to CSV"); doCSV(inputData); } From 982a50fff927b83da1e3958a32f620b034e194a9 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sat, 11 Feb 2017 21:38:09 -0800 Subject: [PATCH 10/33] gonna do this a different way --- json2csv.js | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/json2csv.js b/json2csv.js index 9537bae..bac8151 100644 --- a/json2csv.js +++ b/json2csv.js @@ -44,13 +44,7 @@ if (!module.parent) { } //console.error(JSON.stringify(inputData)); - var chunklength = 100000; - while(inputData.length > chunklength) { - var bigchunk = inputData.splice(0, chunklength-1) - console.error("About to convert chunk of",bigchunk.length,"records to CSV"); - doCSV(bigchunk); - } - console.error("About to convert remaining",inputData.length,"records to CSV"); + console.error("About to convert",inputData.length,"records to CSV"); doCSV(inputData); } From 98c7429828924d86c60cbef1d1b071b726723307 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sat, 11 Feb 2017 22:19:51 -0800 Subject: [PATCH 11/33] This creates a script to split a large json file into manageable chunks --- jsonsplit.sh | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) create mode 100755 jsonsplit.sh diff --git a/jsonsplit.sh b/jsonsplit.sh new file mode 100755 index 0000000..5f8b583 --- /dev/null +++ b/jsonsplit.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +#get input file +inputfile=$1 +partsdir=${inputfile}_parts + +#if not specified, then set the records to 100,000 +if [ -z $2 ] ; then + records=100000 +else + records=$2 +fi + +#create a directory to store the split files +mkdir -p $partsdir + +#splits the input file into (record size) chunks +cat $inputfile | jq -c -M '.[]' | split -l $records - $partsdir/${inputfile}_ + +#before json -g we need to get rid of existing jsons +rm $partsdir/*.json 2>&1 | grep -v "No such file" + +#converts chunked files into json array +cd $partsdir/; ls | while read file; do cat $file | json -g > $file.json; done; cd .. From c9ba62f795bba8c15cd4f4d7d35c9fc331f82a3a Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sat, 11 Feb 2017 22:39:06 -0800 Subject: [PATCH 12/33] renamed --- json2csv.js => complex-json2csv.js | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename json2csv.js => complex-json2csv.js (100%) diff --git a/json2csv.js b/complex-json2csv.js similarity index 100% rename from json2csv.js rename to complex-json2csv.js From 58dbcb6563fbe3eef624239ec80fc4793c6a5482 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sat, 11 Feb 2017 22:42:50 -0800 Subject: [PATCH 13/33] Add running directions --- complex-json2csv.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/complex-json2csv.js b/complex-json2csv.js index bac8151..3298825 100644 --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -1,3 +1,5 @@ +#!/usr/bin/env node + var excerptRows = 7; var input; var url; From 0a55caf72673934eafacc448055be467665e3fde Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sat, 11 Feb 2017 22:45:10 -0800 Subject: [PATCH 14/33] Creating a package.json --- package.json | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 package.json diff --git a/package.json b/package.json new file mode 100644 index 0000000..07f36b0 --- /dev/null +++ b/package.json @@ -0,0 +1,20 @@ +{ + "name": "complex-json2csv", + "preferGlobal": true, + "version": "0.0.1", + "author": "Dana M. Lewis", + "description": "command line json2csv converter that supports super large files and complex, unknown json schemas", + "license": "MIT", + "engines": { + "node": ">=0.10" + }, + "bin": { + "complex-json2csv": "./complex-json2csv.js", + "jsonsplit": "./jsonsplit.sh" + }, + "dependencies": { + "jquery": "~3.1.1", + "jsdom": "~9.11.0" + + } +} From a59a03334ceaf4a3195dee9676fe2d0b0acf8e93 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sun, 12 Feb 2017 02:25:46 -0800 Subject: [PATCH 15/33] disable debug line --- complex-json2csv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) mode change 100644 => 100755 complex-json2csv.js diff --git a/complex-json2csv.js b/complex-json2csv.js old mode 100644 new mode 100755 index 3298825..cd48e5b --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -46,7 +46,7 @@ if (!module.parent) { } //console.error(JSON.stringify(inputData)); - console.error("About to convert",inputData.length,"records to CSV"); + //console.error("About to convert",inputData.length,"records to CSV"); doCSV(inputData); } From acbbe98f6c586882bb3c7d9e615ad8437c69b8c4 Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sun, 12 Feb 2017 02:26:16 -0800 Subject: [PATCH 16/33] clean up filenames; print progress lines --- jsonsplit.sh | 19 +++++++++++++++---- 1 file changed, 15 insertions(+), 4 deletions(-) diff --git a/jsonsplit.sh b/jsonsplit.sh index 5f8b583..f75d36d 100755 --- a/jsonsplit.sh +++ b/jsonsplit.sh @@ -1,7 +1,11 @@ #!/bin/bash +# exit immediately on any errors +set -eu + #get input file -inputfile=$1 +fullinputfile=$1 +inputfile=${fullinputfile%.json} partsdir=${inputfile}_parts #if not specified, then set the records to 100,000 @@ -15,10 +19,17 @@ fi mkdir -p $partsdir #splits the input file into (record size) chunks -cat $inputfile | jq -c -M '.[]' | split -l $records - $partsdir/${inputfile}_ +cat $fullinputfile | jq -c -M '.[]' | split -l $records - $partsdir/${inputfile}_ #before json -g we need to get rid of existing jsons -rm $partsdir/*.json 2>&1 | grep -v "No such file" +rm $partsdir/*.json 2>&1 | grep -v "No such file" || echo -n "" #converts chunked files into json array -cd $partsdir/; ls | while read file; do cat $file | json -g > $file.json; done; cd .. +cd $partsdir/ +ls | while read file; do echo -n "." > /dev/stderr; done; echo > /dev/stderr +ls | while read file; do + cat $file | json -g > $file.json + echo -n "-" > /dev/stderr +done +echo > /dev/stderr +cd .. From 4217360c1be2e9c2f034d1c7494827b8d11ebd9c Mon Sep 17 00:00:00 2001 From: Scott Leibrand Date: Sun, 12 Feb 2017 02:32:44 -0800 Subject: [PATCH 17/33] progress message --- jsonsplit.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/jsonsplit.sh b/jsonsplit.sh index f75d36d..853c0d2 100755 --- a/jsonsplit.sh +++ b/jsonsplit.sh @@ -27,6 +27,7 @@ rm $partsdir/*.json 2>&1 | grep -v "No such file" || echo -n "" #converts chunked files into json array cd $partsdir/ ls | while read file; do echo -n "." > /dev/stderr; done; echo > /dev/stderr +echo "Grouping split records into valid json..." ls | while read file; do cat $file | json -g > $file.json echo -n "-" > /dev/stderr From b1e996ba2b1a591736d6d01c62fcd27d49561ddd Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 17:22:15 -0800 Subject: [PATCH 18/33] Removing web-related functions that are not needed for command line --- complex-json2csv.js | 192 ++++++++++++++++++++++---------------------- 1 file changed, 96 insertions(+), 96 deletions(-) diff --git a/complex-json2csv.js b/complex-json2csv.js index cd48e5b..724b762 100755 --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -1,9 +1,9 @@ #!/usr/bin/env node -var excerptRows = 7; +//var excerptRows = 7; var input; -var url; -var lastSaved; +//var url; +//var lastSaved; // function log(msg) { // return $(".console").removeClass("error").html(msg); @@ -95,31 +95,31 @@ function doJSON() { } // show rendered JSON -function showJSON(rendered) { - console.log("ordered to show JSON: " + rendered); - if (rendered) { - if ($(".json code").html()) { - console.log("there's code to show, showing..."); - $(".json .rendered").show(); - $(".json .editing").hide(); - } - } else { - $(".json .rendered").hide(); - $(".json .editing").show().focus(); - } -} - -function showCSV(rendered) { - if (rendered) { - if ($(".csv table").html()) { - $(".csv .rendered").show(); - $(".csv .editing").hide(); - } - } else { - $(".csv .rendered").hide(); - $(".csv .editing").show().focus(); - } -} +//function showJSON(rendered) { +// console.log("ordered to show JSON: " + rendered); +// if (rendered) { +// if ($(".json code").html()) { +// console.log("there's code to show, showing..."); +// $(".json .rendered").show(); +// $(".json .editing").hide(); +// } +// } else { +// $(".json .rendered").hide(); +// $(".json .editing").show().focus(); +// } +//} + +//function showCSV(rendered) { +// if (rendered) { +// if ($(".csv table").html()) { +// $(".csv .rendered").show(); +// $(".csv .editing").hide(); +// } +// } else { +// $(".csv .rendered").hide(); +// $(".csv .editing").show().focus(); +// } +//} // takes an array of flat JSON objects, converts them to arrays // renders them into a small table as an example @@ -190,48 +190,48 @@ function doCSV(json) { // loads original pasted JSON from textarea, saves to anonymous gist // rate-limiting means this could easily fail with a 403. -function saveJSON() { - if (!input) return false; - if (input == lastSaved) return false; +//function saveJSON() { +// if (!input) return false; +// if (input == lastSaved) return false; // save a permalink to an anonymous gist - var gist = { - description: "test", - public: false, - files: { - "source.json": { - "content": input - } - } - }; +// var gist = { +// description: "test", +// public: false, +// files: { +// "source.json": { +// "content": input +// } +// } +// }; // TODO: show spinner/msg while this happens - console.log("Saving to an anonymous gist..."); - $.post( - 'https://api.github.com/gists', - JSON.stringify(gist) - ).done(function(data, status, xhr) { +// console.log("Saving to an anonymous gist..."); +// $.post( +// 'https://api.github.com/gists', +// JSON.stringify(gist) +// ).done(function(data, status, xhr) { // take new Gist id, make permalink - setPermalink(data.id); +// setPermalink(data.id); // send analytics event - Events.permalink(); +// Events.permalink(); // mark what we last saved - lastSaved = input; +// lastSaved = input; // update error-reporting link, including permalink - setErrorReporting(data.id, input); +// setErrorReporting(data.id, input); - console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); +// console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); - }).fail(function(xhr, status, errorThrown) { - console.log(xhr); +// }).fail(function(xhr, status, errorThrown) { +// console.log(xhr); // send analytics event - Events.permalink_error(status); +// Events.permalink_error(status); // TODO: gracefully handle rate limit errors // if (status == 403) @@ -243,10 +243,10 @@ function saveJSON() { // date.setTime(parseInt(reset) * 1000); // use http://momentjs.com/ to say "in _ minutes" - }); +// }); - return false; -} +// return false; +//} // Updates the error-reporting link to include current details. // @@ -262,57 +262,57 @@ function saveJSON() { // // If no `id` is given, and content is too long, the URL will // encode only a title, and no body. -function setErrorReporting(id, content) { - var base = "https://github.com/konklone/json/issues/new"; +//function setErrorReporting(id, content) { +// var base = "https://github.com/konklone/json/issues/new"; - var title = "Error parsing some specific JSON"; +// var title = "Error parsing some specific JSON"; - var body = "I'm having an issue converting this JSON:\n\n"; - if (id) body += ( - window.location.protocol + "//" + - window.location.host + window.location.pathname + - "?id=" + id + "\n\n" - ); +// var body = "I'm having an issue converting this JSON:\n\n"; +// if (id) body += ( +// window.location.protocol + "//" + +// window.location.host + window.location.pathname + +// "?id=" + id + "\n\n" +// ); - if (content.length <= (7 * 1024)) - body += ("```json\n" + content + "\n```"); +// if (content.length <= (7 * 1024)) +// body += ("```json\n" + content + "\n```"); - var finalUrl = base + "?title=" + encodeURIComponent(title) + - "&body=" + encodeURIComponent(body); +// var finalUrl = base + "?title=" + encodeURIComponent(title) + +// "&body=" + encodeURIComponent(body); - $(".error a.report").attr("href", finalUrl); +// $(".error a.report").attr("href", finalUrl); // console.log("Updated error reporting link to:" + finalUrl); - return true; -} +// return true; +/} // given a valid gist ID, set the permalink to use it -function setPermalink(id) { - if (history && history.pushState) - history.pushState({id: id}, null, "?id=" + id); +//function setPermalink(id) { +// if (history && history.pushState) +// history.pushState({id: id}, null, "?id=" + id); // log("Permalink created! (Copy from the location bar.)") -} +//} // check query string for gist ID -function loadPermalink() { - var id = getParam("id"); - if (!id) return; - - $.get('https://api.github.com/gists/' + id, - function(data, status, xhr) { - console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); - - var input = data.files["source.json"].content; - $(".json textarea").val(input); - doJSON(); - showJSON(true); - } - ).fail(function(xhr, status, errorThrown) { - console.log("Error fetching anonymous gist!"); - console.log(xhr); - console.log(status); - console.log(errorThrown); - }); -} +//function loadPermalink() { +// var id = getParam("id"); +// if (!id) return; + +// $.get('https://api.github.com/gists/' + id, +// function(data, status, xhr) { +// console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); + +// var input = data.files["source.json"].content; +// $(".json textarea").val(input); +// doJSON(); +// showJSON(true); +// } +// ).fail(function(xhr, status, errorThrown) { +// console.log("Error fetching anonymous gist!"); +// console.log(xhr); +// console.log(status); +// console.log(errorThrown); +// }); +/} From f84cf0c1e3cb2c7ef32fc8df9cdaed8937cd3861 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 17:23:20 -0800 Subject: [PATCH 19/33] Typo fix for commenting out --- complex-json2csv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/complex-json2csv.js b/complex-json2csv.js index 724b762..7b5ff2f 100755 --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -284,7 +284,7 @@ function doCSV(json) { // console.log("Updated error reporting link to:" + finalUrl); // return true; -/} +//} // given a valid gist ID, set the permalink to use it //function setPermalink(id) { From 26d06fc7638a86ff0ee492c10b57410477e71ce9 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 17:23:40 -0800 Subject: [PATCH 20/33] Another missed / --- complex-json2csv.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/complex-json2csv.js b/complex-json2csv.js index 7b5ff2f..a20e7b1 100755 --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -314,5 +314,5 @@ function doCSV(json) { // console.log(status); // console.log(errorThrown); // }); -/} +//} From fcb982e08173f3350437e830d95b76170eae5ef1 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 17:26:12 -0800 Subject: [PATCH 21/33] Uncomment showCSV --- complex-json2csv.js | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/complex-json2csv.js b/complex-json2csv.js index a20e7b1..8a05d2d 100755 --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -109,17 +109,17 @@ function doJSON() { // } //} -//function showCSV(rendered) { -// if (rendered) { -// if ($(".csv table").html()) { -// $(".csv .rendered").show(); -// $(".csv .editing").hide(); -// } -// } else { -// $(".csv .rendered").hide(); -// $(".csv .editing").show().focus(); -// } -//} +function showCSV(rendered) { + if (rendered) { + if ($(".csv table").html()) { + $(".csv .rendered").show(); + $(".csv .editing").hide(); + } + } else { + $(".csv .rendered").hide(); + $(".csv .editing").show().focus(); + } +} // takes an array of flat JSON objects, converts them to arrays // renders them into a small table as an example From cb81c75dacc50bd65c4af5565d1562405561d037 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 17:31:15 -0800 Subject: [PATCH 22/33] Removing web-version related code unneeded for command line usage --- complex-json2csv.js | 164 -------------------------------------------- 1 file changed, 164 deletions(-) diff --git a/complex-json2csv.js b/complex-json2csv.js index 8a05d2d..36fb2eb 100755 --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -1,17 +1,6 @@ #!/usr/bin/env node -//var excerptRows = 7; var input; -//var url; -//var lastSaved; - -// function log(msg) { -// return $(".console").removeClass("error").html(msg); -// } - -// function error(msg) { -// return log(msg).addClass("error"); -// } function usage ( ) { console.log('usage: ', process.argv.slice(0, 2), 'inputfile.json'); @@ -94,20 +83,6 @@ function doJSON() { return true; } -// show rendered JSON -//function showJSON(rendered) { -// console.log("ordered to show JSON: " + rendered); -// if (rendered) { -// if ($(".json code").html()) { -// console.log("there's code to show, showing..."); -// $(".json .rendered").show(); -// $(".json .editing").hide(); -// } -// } else { -// $(".json .rendered").hide(); -// $(".json .editing").show().focus(); -// } -//} function showCSV(rendered) { if (rendered) { @@ -177,142 +152,3 @@ function doCSV(json) { // excerpt and render first 10 rows //renderCSV(outArray.slice(0, excerptRows)); showCSV(true); - - // show raw data if people really want it - //$(".csv textarea").val(csv); - - // download link to entire CSV as data - // thanks to https://jsfiddle.net/terryyounghk/KPEGU/ - // and https://stackoverflow.com/questions/14964035/how-to-export-javascript-array-info-to-csv-on-client-side - //var uri = "data:text/csv;charset=utf-8," + encodeURIComponent(csv); - //$(".csv a.download").attr("href", uri); -} - -// loads original pasted JSON from textarea, saves to anonymous gist -// rate-limiting means this could easily fail with a 403. -//function saveJSON() { -// if (!input) return false; -// if (input == lastSaved) return false; - - // save a permalink to an anonymous gist -// var gist = { -// description: "test", -// public: false, -// files: { -// "source.json": { -// "content": input -// } -// } -// }; - - // TODO: show spinner/msg while this happens - -// console.log("Saving to an anonymous gist..."); -// $.post( -// 'https://api.github.com/gists', -// JSON.stringify(gist) -// ).done(function(data, status, xhr) { - - // take new Gist id, make permalink -// setPermalink(data.id); - - // send analytics event -// Events.permalink(); - - // mark what we last saved -// lastSaved = input; - - // update error-reporting link, including permalink -// setErrorReporting(data.id, input); - -// console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); - -// }).fail(function(xhr, status, errorThrown) { -// console.log(xhr); - - // send analytics event -// Events.permalink_error(status); - - // TODO: gracefully handle rate limit errors - // if (status == 403) - - // TODO: show when saving will be available - // e.g. "try again in 5 minutes" - // var reset = xhr.getResponseHeader("X-RateLimit-Reset"); - // var date = new Date(); - // date.setTime(parseInt(reset) * 1000); - // use http://momentjs.com/ to say "in _ minutes" - -// }); - -// return false; -//} - -// Updates the error-reporting link to include current details. -// -// If the passed-in `id` is not null, a permalink is included. -// If the passed-in `id` is null, then no permalink is included. -// (Needed explicitly because the current URL doesn't always refer -// to a permalink related to the current value of the textarea.) -// -// The current body of the textarea will be encoded into the URI, -// to pre-populate the GitHub issue template, but only if the body -// is < 7KB (7,168). GitHub's nginx server rejects query strings -// longer than ~8KB. -// -// If no `id` is given, and content is too long, the URL will -// encode only a title, and no body. -//function setErrorReporting(id, content) { -// var base = "https://github.com/konklone/json/issues/new"; - -// var title = "Error parsing some specific JSON"; - -// var body = "I'm having an issue converting this JSON:\n\n"; -// if (id) body += ( -// window.location.protocol + "//" + -// window.location.host + window.location.pathname + -// "?id=" + id + "\n\n" -// ); - -// if (content.length <= (7 * 1024)) -// body += ("```json\n" + content + "\n```"); - -// var finalUrl = base + "?title=" + encodeURIComponent(title) + -// "&body=" + encodeURIComponent(body); - -// $(".error a.report").attr("href", finalUrl); - - // console.log("Updated error reporting link to:" + finalUrl); -// return true; -//} - -// given a valid gist ID, set the permalink to use it -//function setPermalink(id) { -// if (history && history.pushState) -// history.pushState({id: id}, null, "?id=" + id); - - // log("Permalink created! (Copy from the location bar.)") -//} - -// check query string for gist ID -//function loadPermalink() { -// var id = getParam("id"); -// if (!id) return; - -// $.get('https://api.github.com/gists/' + id, -// function(data, status, xhr) { -// console.log("Remaining this hour: " + xhr.getResponseHeader("X-RateLimit-Remaining")); - -// var input = data.files["source.json"].content; -// $(".json textarea").val(input); -// doJSON(); -// showJSON(true); -// } -// ).fail(function(xhr, status, errorThrown) { -// console.log("Error fetching anonymous gist!"); -// console.log(xhr); -// console.log(status); -// console.log(errorThrown); -// }); -//} - From a55c91ba8bf40c6367ea9c67270d4598aa0bf93b Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 17:44:20 -0800 Subject: [PATCH 23/33] Add missing } --- complex-json2csv.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/complex-json2csv.js b/complex-json2csv.js index 36fb2eb..8c984d1 100755 --- a/complex-json2csv.js +++ b/complex-json2csv.js @@ -152,3 +152,5 @@ function doCSV(json) { // excerpt and render first 10 rows //renderCSV(outArray.slice(0, excerptRows)); showCSV(true); + +} From c487490ed68d62acd727a62cf3a5275a53540807 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 17:53:08 -0800 Subject: [PATCH 24/33] Update README.md --- README.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 4329ef5..e7c9991 100644 --- a/README.md +++ b/README.md @@ -2,4 +2,19 @@ A simple JSON to CSV converter that handles objects and nested documents. -Previously a browser-side tool; attempting to turn it into a command line tool. Based on https://github.com/konklone/json. +* In the **web** version, conversion happens inside the browser, in straight JavaScript. It may choke on large files. +* With complex-csv2json.js, it can be run via the **command line**. It uses jsonsplit.sh to deal with large files. + +Please file all bugs [in the issue tracker](https://github.com/konklone/json/issues). + +Read more about the converter and why I built it: "[Making JSON as simple as a spreadsheet](http://sunlightfoundation.com/blog/2014/03/11/making-json-as-simple-as-a-spreadsheet/)". + +## Public domain + +This project makes uses of certain externally licensed works, including (but not limited to) Bootstrap, Highlight.js, jQuery and jquery-csv. Any such works retain their original license, even if they have been subsequently modified by me. + +All **other files** in this project are [dedicated to the public domain](LICENSE). As spelled out in [CONTRIBUTING](CONTRIBUTING.md): + +> The project is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](http://creativecommons.org/publicdomain/zero/1.0/). + +> All contributions to this project will be released under the CC0 dedication. By submitting a pull request, you are agreeing to comply with this waiver of copyright interest. From 5f2aa9173567b38bb1291af3a23fad36d6aa41ea Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:16:21 -0800 Subject: [PATCH 25/33] Add command line instructions to README --- README.md | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/README.md b/README.md index e7c9991..1cd170e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,13 @@ A simple JSON to CSV converter that handles objects and nested documents. * In the **web** version, conversion happens inside the browser, in straight JavaScript. It may choke on large files. * With complex-csv2json.js, it can be run via the **command line**. It uses jsonsplit.sh to deal with large files. +To install and run via the command line: +* `npm install -g complex-json2csv` +* type the name of the command and provide an input file (`complex-json2csv inputfile.json`) + * This will print the output to the screen. + * To create a csv file: `complex-json2csv inputfile.json > outputfile.csv` + + Please file all bugs [in the issue tracker](https://github.com/konklone/json/issues). Read more about the converter and why I built it: "[Making JSON as simple as a spreadsheet](http://sunlightfoundation.com/blog/2014/03/11/making-json-as-simple-as-a-spreadsheet/)". From 1c78c79972e948155340f61fb786f3a45cfa20bd Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:36:56 -0800 Subject: [PATCH 26/33] Bug fixed for no input file and unspecified record length plus error checking --- jsonsplit.sh | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/jsonsplit.sh b/jsonsplit.sh index 853c0d2..b418077 100755 --- a/jsonsplit.sh +++ b/jsonsplit.sh @@ -3,18 +3,25 @@ # exit immediately on any errors set -eu -#get input file -fullinputfile=$1 -inputfile=${fullinputfile%.json} -partsdir=${inputfile}_parts +# echo $# #if not specified, then set the records to 100,000 -if [ -z $2 ] ; then +if [ $# -eq 0 ]; then + echo "Error: Please provide an input file. " + echo "Usage: $0 inputfile.json [records]" + exit +elif [ $# -eq 1 ]; then +# if [ -z ${2=x} ]; then records=100000 else records=$2 fi +#get input file +fullinputfile=$1 +inputfile=${fullinputfile%.json} +partsdir=${inputfile}_parts + #create a directory to store the split files mkdir -p $partsdir From 189b91670f23f414095633d54a5a3da8fd9c7357 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:42:04 -0800 Subject: [PATCH 27/33] Clean up previous error checking no longer needed --- jsonsplit.sh | 3 --- 1 file changed, 3 deletions(-) diff --git a/jsonsplit.sh b/jsonsplit.sh index b418077..126852a 100755 --- a/jsonsplit.sh +++ b/jsonsplit.sh @@ -3,15 +3,12 @@ # exit immediately on any errors set -eu - -# echo $# #if not specified, then set the records to 100,000 if [ $# -eq 0 ]; then echo "Error: Please provide an input file. " echo "Usage: $0 inputfile.json [records]" exit elif [ $# -eq 1 ]; then -# if [ -z ${2=x} ]; then records=100000 else records=$2 From dab89afe8d2fcad60b400c483026f1a8425c8bcb Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:42:34 -0800 Subject: [PATCH 28/33] Update README with clarified command line instructions for each tool --- README.md | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index 1cd170e..1a41f02 100644 --- a/README.md +++ b/README.md @@ -7,9 +7,12 @@ A simple JSON to CSV converter that handles objects and nested documents. To install and run via the command line: * `npm install -g complex-json2csv` -* type the name of the command and provide an input file (`complex-json2csv inputfile.json`) - * This will print the output to the screen. - * To create a csv file: `complex-json2csv inputfile.json > outputfile.csv` +* type the name of the command and provide an input file + * `complex-json2csv inputfile.json` - this will print the output to the screen. + * `complex-json2csv inputfile.json > outputfile.csv` - this will print output to a csv file + * `jsonsplit inputfile.json [records]` - this will split the file into records based on the [records] size + * If you do not specify size, it defaults to splitting by 100000 + Please file all bugs [in the issue tracker](https://github.com/konklone/json/issues). From a2aea2773e7d28d5b4d7c67c3b350515c017af9d Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:46:46 -0800 Subject: [PATCH 29/33] Adjust README for npm patch --- README.md | 17 ++--------------- 1 file changed, 2 insertions(+), 15 deletions(-) diff --git a/README.md b/README.md index 1a41f02..724abfb 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -## JSON to CSV Converter +## Complex JSON to CSV Converter A simple JSON to CSV converter that handles objects and nested documents. @@ -14,17 +14,4 @@ To install and run via the command line: * If you do not specify size, it defaults to splitting by 100000 - -Please file all bugs [in the issue tracker](https://github.com/konklone/json/issues). - -Read more about the converter and why I built it: "[Making JSON as simple as a spreadsheet](http://sunlightfoundation.com/blog/2014/03/11/making-json-as-simple-as-a-spreadsheet/)". - -## Public domain - -This project makes uses of certain externally licensed works, including (but not limited to) Bootstrap, Highlight.js, jQuery and jquery-csv. Any such works retain their original license, even if they have been subsequently modified by me. - -All **other files** in this project are [dedicated to the public domain](LICENSE). As spelled out in [CONTRIBUTING](CONTRIBUTING.md): - -> The project is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](http://creativecommons.org/publicdomain/zero/1.0/). - -> All contributions to this project will be released under the CC0 dedication. By submitting a pull request, you are agreeing to comply with this waiver of copyright interest. +(Web tool originally from https://github.com/konklone/json; command line tool complex-csv2json and jsonsplit by [@DanaMLewis](https://github.com/danamlewis).) From 33a5d60711ca77593a6a611f863fbb2de2525543 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:48:24 -0800 Subject: [PATCH 30/33] 0.0.2 --- package.json | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/package.json b/package.json index 07f36b0..9029f10 100644 --- a/package.json +++ b/package.json @@ -1,20 +1,19 @@ { - "name": "complex-json2csv", - "preferGlobal": true, - "version": "0.0.1", - "author": "Dana M. Lewis", - "description": "command line json2csv converter that supports super large files and complex, unknown json schemas", - "license": "MIT", - "engines": { - "node": ">=0.10" - }, - "bin": { - "complex-json2csv": "./complex-json2csv.js", - "jsonsplit": "./jsonsplit.sh" - }, - "dependencies": { - "jquery": "~3.1.1", - "jsdom": "~9.11.0" - - } + "name": "complex-json2csv", + "preferGlobal": true, + "version": "0.0.2", + "author": "Dana M. Lewis", + "description": "command line json2csv converter that supports super large files and complex, unknown json schemas", + "license": "MIT", + "engines": { + "node": ">=0.10" + }, + "bin": { + "complex-json2csv": "./complex-json2csv.js", + "jsonsplit": "./jsonsplit.sh" + }, + "dependencies": { + "jquery": "~3.1.1", + "jsdom": "~9.11.0" + } } From ab2bb20cd16f91a74f3eb4478a62906fe15c84e9 Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:52:59 -0800 Subject: [PATCH 31/33] 0.0.3 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9029f10..923d5d1 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "complex-json2csv", "preferGlobal": true, - "version": "0.0.2", + "version": "0.0.3", "author": "Dana M. Lewis", "description": "command line json2csv converter that supports super large files and complex, unknown json schemas", "license": "MIT", From 32ba6d01b9c349ed028d7c8442a7ef3f4f1b7b6f Mon Sep 17 00:00:00 2001 From: Dana Lewis Date: Sun, 12 Feb 2017 18:57:00 -0800 Subject: [PATCH 32/33] Re-convert README to prep for PR to konklone --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 724abfb..59a94c9 100644 --- a/README.md +++ b/README.md @@ -13,5 +13,18 @@ To install and run via the command line: * `jsonsplit inputfile.json [records]` - this will split the file into records based on the [records] size * If you do not specify size, it defaults to splitting by 100000 - (Web tool originally from https://github.com/konklone/json; command line tool complex-csv2json and jsonsplit by [@DanaMLewis](https://github.com/danamlewis).) + +Please file all bugs [in the issue tracker](https://github.com/konklone/json/issues). + +Read more about the converter and why I (@konklone) built it: "[Making JSON as simple as a spreadsheet](http://sunlightfoundation.com/blog/2014/03/11/making-json-as-simple-as-a-spreadsheet/)". + +## Public domain + +This project makes uses of certain externally licensed works, including (but not limited to) Bootstrap, Highlight.js, jQuery and jquery-csv. Any such works retain their original license, even if they have been subsequently modified by me. + +All **other files** in this project are [dedicated to the public domain](LICENSE). As spelled out in [CONTRIBUTING](CONTRIBUTING.md): + +> The project is in the public domain within the United States, and copyright and related rights in the work worldwide are waived through the [CC0 1.0 Universal public domain dedication](http://creativecommons.org/publicdomain/zero/1.0/). + +> All contributions to this project will be released under the CC0 dedication. By submitting a pull request, you are agreeing to comply with this waiver of copyright interest. From b77f00676c5935c1dee1aa633f306dbaabb69df7 Mon Sep 17 00:00:00 2001 From: Eden Grown-Haeberli Date: Fri, 20 Apr 2018 16:57:19 -0700 Subject: [PATCH 33/33] update dependencies in README --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 59a94c9..bc513f5 100644 --- a/README.md +++ b/README.md @@ -13,6 +13,9 @@ To install and run via the command line: * `jsonsplit inputfile.json [records]` - this will split the file into records based on the [records] size * If you do not specify size, it defaults to splitting by 100000 +If not yet already done, also remember to install `json` via the command line: + * `npm install -g json` + (Web tool originally from https://github.com/konklone/json; command line tool complex-csv2json and jsonsplit by [@DanaMLewis](https://github.com/danamlewis).) Please file all bugs [in the issue tracker](https://github.com/konklone/json/issues).