Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

jsonexport

Package Overview
Dependencies
Maintainers
3
Versions
43
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

jsonexport - npm Package Compare versions

Comparing version 2.0.11 to 2.1.0

.appveyor.yml

4

dist/parser/csv.js

@@ -178,3 +178,3 @@ /* jshint node:true */

//Items are returned as a object {item: 'Prop Value, Item Name', value: 'Prop Data Value'}
var itemResult = self._handler.check(item, self._options.mainPathItem);
var itemResult = self._handler.check(item, self._options.mainPathItem, item, json);
fillRows(itemResult);

@@ -230,3 +230,3 @@ }

if (this._options.mainPathItem) prefix = this._options.mainPathItem + this._options.headerPathString;
parseResult = this._handler.check(json[prop], prefix + prop);
parseResult = this._handler.check(json[prop], prefix + prop, prop, json);

@@ -233,0 +233,0 @@ parseResult.forEach(fillRows);

/* jshint node:true */
'use strict';
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; };
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();

@@ -15,8 +17,20 @@

this._options = options;
this._options.handleString = this._options.handleString || this._handleString;
this._options.handleNumber = this._options.handleNumber || this._handleNumber;
this._options.handleBoolean = this._options.handleBoolean || this._handleBoolean;
this._options.handleDate = this._options.handleDate || this._handleDate;
//an object of {typeName:(value,index,parent)=>any}
this._options.typeHandlers = this._options.typeHandlers || {};
//deprecated options
this._options.handleString = this._options.handleString ? warnDepOp('handleString', this._options.handleString) : this._handleString;
this._options.handleNumber = this._options.handleNumber ? warnDepOp('handleNumber', this._options.handleNumber) : this._handleNumber;
this._options.handleBoolean = this._options.handleBoolean ? warnDepOp('handleBoolean', this._options.handleBoolean) : this._handleBoolean;
this._options.handleDate = this._options.handleDate ? warnDepOp('handleDate', this._options.handleDate) : this._handleDate;
}
/**
* Check if results needing mapping to alternate value
*
* @returns [{item, value}] result
*/
_createClass(Handler, [{

@@ -32,2 +46,43 @@ key: '_setHeaders',

}
}, {
key: 'castValue',
value: function castValue(element, item, index, parent) {
//cast by matching constructor
var types = this._options.typeHandlers;
for (var type in types) {
if (isInstanceOfTypeName(element, type)) {
element = types[type].call(types, element, index, parent);
break; //first match we move on
}
}
return element;
}
}, {
key: 'checkComplex',
value: function checkComplex(element, item) {
//Check if element is a Date
if (helper.isDate(element)) {
return [{
item: item,
value: this._options.handleDate(element, item)
}];
}
//Check if element is an Array
else if (helper.isArray(element)) {
var resultArray = this._handleArray(element, item);
return this._setHeaders(resultArray, item);
}
//Check if element is a Object
else if (helper.isObject(element)) {
var resultObject = this._handleObject(element);
return this._setHeaders(resultObject, item);
}
return [{
item: item,
value: ''
}];
}
/**

@@ -38,2 +93,3 @@ * Check the element type of the element call the correct handle function

* @param item Used to make the headers/path breadcrumb
* @returns [{item, value}] result
*/

@@ -43,46 +99,27 @@

key: 'check',
value: function check(element, item) {
//Check if element is a String
if (helper.isString(element)) {
return [{
item: item,
value: this._options.handleString(element, item)
}];
}
//Check if element is a Number
else if (helper.isNumber(element)) {
value: function check(element, item, index, parent) {
element = this.castValue(element, item, index, parent);
//try simple value by highier performance switch
switch (typeof element === 'undefined' ? 'undefined' : _typeof(element)) {
case 'string':
return [{
item: item,
value: this._options.handleString(element, item)
}];
case 'number':
return [{
item: item,
value: this._options.handleNumber(element, item)
}];
}
//Check if element is a Boolean
else if (helper.isBoolean(element)) {
return [{
item: item,
value: this._options.handleBoolean.bind(this)(element, item)
}];
}
//Check if element is a Date
else if (helper.isDate(element)) {
return [{
item: item,
value: this._options.handleDate(element, item)
}];
}
//Check if element is an Array
else if (helper.isArray(element)) {
var resultArray = this._handleArray(element, item);
return this._setHeaders(resultArray, item);
}
//Check if element is a Object
else if (helper.isObject(element)) {
var resultObject = this._handleObject(element, item);
return this._setHeaders(resultObject, item);
}
return [{
item: item,
value: ''
}];
case 'boolean':
return [{
item: item,
value: this._options.handleBoolean.bind(this)(element, item)
}];
}
return this.checkComplex(element, item);
}

@@ -94,3 +131,3 @@

* @param {Object} obj
* @returns {Array} result
* @returns [{item, value}] result
*/

@@ -106,4 +143,4 @@

//Check the propData type
var resultCheckType = this.check(propData, prop);
//Append to results
var resultCheckType = this.check(propData, prop, prop, obj);
//Append to results aka merge results aka array-append-array
result = result.concat(resultCheckType);

@@ -113,2 +150,3 @@ }

}
/**

@@ -118,3 +156,3 @@ * Handle all Arrays, merges arrays with primitive types in a single value

* @param {Array} array
* @returns {Array} result
* @returns [{item, value}] result
*/

@@ -128,39 +166,18 @@

var firstElementWithoutItem;
var _iteratorNormalCompletion = true;
var _didIteratorError = false;
var _iteratorError = undefined;
try {
for (var _iterator = array[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) {
var element = _step.value;
//Check the propData type
var resultCheckType = self.check(element);
//Check for results without itens, merge all itens with the first occurrence
if (resultCheckType.length === 0) continue;
var firstResult = resultCheckType[0];
if (!firstResult.item && firstElementWithoutItem !== undefined) {
firstElementWithoutItem.value += self._options.arrayPathString + firstResult.value;
continue;
} else if (resultCheckType.length > 0 && !firstResult.item && firstElementWithoutItem === undefined) {
firstElementWithoutItem = firstResult;
}
//Append to results
result = result.concat(resultCheckType);
for (var aIndex = 0; aIndex < array.length; ++aIndex) {
var element = array[aIndex];
//Check the propData type
var resultCheckType = self.check(element, null, aIndex, array);
//Check for results without itens, merge all itens with the first occurrence
if (resultCheckType.length === 0) continue;
var firstResult = resultCheckType[0];
if (!firstResult.item && firstElementWithoutItem !== undefined) {
firstElementWithoutItem.value += self._options.arrayPathString + firstResult.value;
continue;
} else if (resultCheckType.length > 0 && !firstResult.item && firstElementWithoutItem === undefined) {
firstElementWithoutItem = firstResult;
}
} catch (err) {
_didIteratorError = true;
_iteratorError = err;
} finally {
try {
if (!_iteratorNormalCompletion && _iterator.return) {
_iterator.return();
}
} finally {
if (_didIteratorError) {
throw _iteratorError;
}
}
//Append to results
result = result.concat(resultCheckType);
}
return result;

@@ -228,2 +245,26 @@ }

module.exports = Handler;
module.exports = Handler;
function warnDepOp(optionName, backOut) {
console.warn("[jsonexport]: option " + optionName + " has been deprecated. Use option.typeHandlers");
return backOut;
}
var globalScope = typeof window === "undefined" ? global : window;
function isInstanceOfTypeName(element, typeName) {
if (element instanceof globalScope[typeName]) {
return true; //Buffer and complex objects
}
//literals in javascript cannot be checked by instance of
switch (typeof element === 'undefined' ? 'undefined' : _typeof(element)) {
case 'string':
return typeName === "String";
case 'boolean':
return typeName === "Boolean";
case 'number':
return typeName === "Number";
}
return false;
}

@@ -101,3 +101,3 @@ /* jshint node:true */

//Items are returned as a object {item: 'Prop Value, Item Name', value: 'Prop Data Value'}
let itemResult = self._handler.check(item, self._options.mainPathItem);
let itemResult = self._handler.check(item, self._options.mainPathItem, item, json);
fillRows(itemResult);

@@ -142,3 +142,3 @@ }

prefix = this._options.mainPathItem + this._options.headerPathString;
parseResult = this._handler.check(json[prop], prefix + prop);
parseResult = this._handler.check(json[prop], prefix + prop, prop, json);

@@ -145,0 +145,0 @@ parseResult.forEach(fillRows);

@@ -9,8 +9,18 @@ /* jshint node:true */

this._options = options;
this._options.handleString = this._options.handleString || this._handleString;
this._options.handleNumber = this._options.handleNumber || this._handleNumber;
this._options.handleBoolean = this._options.handleBoolean || this._handleBoolean;
this._options.handleDate = this._options.handleDate || this._handleDate;
//an object of {typeName:(value,index,parent)=>any}
this._options.typeHandlers = this._options.typeHandlers || {};
//deprecated options
this._options.handleString = this._options.handleString ? warnDepOp('handleString', this._options.handleString) : this._handleString;
this._options.handleNumber = this._options.handleNumber ? warnDepOp('handleNumber', this._options.handleNumber) : this._handleNumber;
this._options.handleBoolean = this._options.handleBoolean ? warnDepOp('handleBoolean', this._options.handleBoolean) : this._handleBoolean;
this._options.handleDate = this._options.handleDate ? warnDepOp('handleDate', this._options.handleDate) : this._handleDate;
}
/**
* Check if results needing mapping to alternate value
*
* @returns [{item, value}] result
*/
_setHeaders(result, item) {

@@ -24,32 +34,19 @@ let self = this;

}
/**
* Check the element type of the element call the correct handle function
*
* @param element Element that will be checked
* @param item Used to make the headers/path breadcrumb
*/
check(element, item) {
//Check if element is a String
if (helper.isString(element)) {
return [{
item: item,
value: this._options.handleString(element, item),
}];
castValue(element, item, index, parent){
//cast by matching constructor
const types = this._options.typeHandlers;
for (let type in types ) {
if( isInstanceOfTypeName(element,type) ){
element = types[type].call(types, element, index, parent);
break;//first match we move on
}
}
//Check if element is a Number
else if (helper.isNumber(element)) {
return [{
item: item,
value: this._options.handleNumber(element, item),
}];
}
//Check if element is a Boolean
else if (helper.isBoolean(element)) {
return [{
item: item,
value: this._options.handleBoolean.bind(this)(element, item),
}];
}
return element;
}
checkComplex(element, item){
//Check if element is a Date
else if (helper.isDate(element)) {
if (helper.isDate(element)) {
return [{

@@ -67,3 +64,3 @@ item: item,

else if (helper.isObject(element)) {
var resultObject = this._handleObject(element, item);
var resultObject = this._handleObject(element);
return this._setHeaders(resultObject, item);

@@ -77,4 +74,38 @@ }

}
/**
* Check the element type of the element call the correct handle function
*
* @param element Element that will be checked
* @param item Used to make the headers/path breadcrumb
* @returns [{item, value}] result
*/
check(element, item, index, parent) {
element = this.castValue(element, item, index, parent);
//try simple value by highier performance switch
switch(typeof element){
case 'string':
return [{
item: item,
value: this._options.handleString(element, item),
}];
case 'number':
return [{
item: item,
value: this._options.handleNumber(element, item),
}];
case 'boolean':
return [{
item: item,
value: this._options.handleBoolean.bind(this)(element, item),
}];
}
return this.checkComplex(element, item);
}
/**

@@ -84,3 +115,3 @@ * Handle all Objects

* @param {Object} obj
* @returns {Array} result
* @returns [{item, value}] result
*/

@@ -93,4 +124,4 @@ _handleObject(obj) {

//Check the propData type
var resultCheckType = this.check(propData, prop);
//Append to results
var resultCheckType = this.check(propData, prop, prop, obj);
//Append to results aka merge results aka array-append-array
result = result.concat(resultCheckType);

@@ -100,2 +131,3 @@ }

}
/**

@@ -105,3 +137,3 @@ * Handle all Arrays, merges arrays with primitive types in a single value

* @param {Array} array
* @returns {Array} result
* @returns [{item, value}] result
*/

@@ -112,5 +144,6 @@ _handleArray(array) {

var firstElementWithoutItem;
for (let element of array) {
for (let aIndex=0; aIndex < array.length; ++aIndex) {
let element = array[aIndex];
//Check the propData type
var resultCheckType = self.check(element);
var resultCheckType = self.check(element, null, aIndex, array);
//Check for results without itens, merge all itens with the first occurrence

@@ -177,1 +210,22 @@ if (resultCheckType.length === 0) continue;

module.exports = Handler;
function warnDepOp(optionName, backOut){
console.warn("[jsonexport]: option "+optionName+" has been deprecated. Use option.typeHandlers");
return backOut;
}
const globalScope = typeof(window)==="undefined" ? global : window;
function isInstanceOfTypeName(element, typeName){
if( element instanceof globalScope[typeName] ){
return true;//Buffer and complex objects
}
//literals in javascript cannot be checked by instance of
switch( typeof(element) ){
case 'string':return typeName==="String";
case 'boolean':return typeName==="Boolean";
case 'number':return typeName==="Number";
}
return false;
}
{
"name": "jsonexport",
"version": "2.0.11",
"version": "2.1.0",
"description": "Makes easy to convert JSON to CSV",

@@ -9,3 +9,3 @@ "main": "./lib",

"lint": "./node_modules/.bin/jshint ./lib/index.js",
"build:dist": "babel lib --out-dir dist --presets=es2015"
"build:dist": "babel lib --out-dir dist --presets=env"
},

@@ -41,3 +41,3 @@ "pre-commit": [

"author": "Kauê Gimenes",
"license": "ISC",
"license": "Apache-2.0",
"bugs": {

@@ -49,7 +49,7 @@ "url": "https://github.com/kauegimenes/jsonexport/issues"

"babel-cli": "^6.26.0",
"babel-preset-es2015": "^6.24.1",
"babel-preset-env": "^1.6.1",
"benchmark": "^2.1.4",
"chai": "^4.0.1",
"jshint": "^2.9.4",
"mocha": "^3.1.0",
"jshint": "^2.9.5",
"mocha": "^5.1.1",
"pre-commit": "^1.2.2"

@@ -56,0 +56,0 @@ },

@@ -11,2 +11,3 @@ # jsonexport

[![NPM License](https://img.shields.io/npm/l/jsonexport.svg?style=flat)](https://www.npmjs.org/package/jsonexport)
[![GitHub stars](https://img.shields.io/github/stars/kauegimenes/jsonexport.svg)](https://github.com/kauegimenes/jsonexport/stargazers)
[![Try jsonexport on RunKit](https://badge.runkitcdn.com/jsonexport.svg)](https://npm.runkit.com/jsonexport)

@@ -18,2 +19,4 @@

[Online Demo Page](http://kauegimenes.github.io/jsonexport/demo/)
<details>

@@ -25,5 +28,10 @@ <summary><b>Table of Contents</b></summary>

- [Browser](#browser)
- [Browser Import Examples](#browser-import-examples)
- [Stream](#stream)
- [JSON Array Example](#json-array-example)
- [Customization](#customization)
- [Simple Array](#simple-array)
- [JSON Object Example](#json-object-example)
- [Options](#options)
- [typeHandlers](#typehandlers)
- [Contributors](#contributors)

@@ -236,8 +244,6 @@ </details>

## Customization
## Options
In order to get the most of out of this module, you can customize many parameters and functions.
#### Options
- `headerPathString` - `String` Used to create the propriety path, defaults to `.` example `contact: {name: 'example}` = `contact.name`

@@ -260,2 +266,5 @@ - `fillGaps` - `Boolean` Set this option if don't want to have empty cells in case of an object with multiple nested items (array prop), defaults to `false` [Issue #22](https://github.com/kauegimenes/jsonexport/issues/22)

- `verticalOutput` - `Boolean` Set this option to false to create a horizontal output for JSON Objects, headers in the first row, values in the second.
- `typeHandlers` - `{typeName:(value, index, parent)=>any` A key map of constructors used to match by instance to create a value using the defined function ([see example](#typehandlers))
**Deprecated Options** (Use typeHandlers)
- `handleString` - `Function` Use this to customize all `Strings` in the CSV file.

@@ -266,5 +275,5 @@ - `handleNumber` - `Function` Use this to customize all `Numbers` in the CSV file.

### Handle Function Option Example
Lets say you want to prepend a text to every string in your CSV file, how to do it?
#### typeHandlers
Define types by constructors and what function to run when that type is matched

@@ -274,11 +283,36 @@ ```javascript

var options = {
handleString: function(string, name){
return 'Hey - ' + string;
}
//data
var contacts = {
'a' : Buffer.from('a2b', 'utf8'),
'b' : Buffer.from('other field', 'utf8'),
'x' : 22,
'z' : function(){return 'bad ace'}
};
jsonexport({lang: 'Node.js',module: 'jsonexport'}, options, function(err, csv){
if(err) return console.log(err);
console.log(csv);
var options={
//definitions to type cast
typeHandlers:{
Array:function(value,index,parent){
return 'replaced-array';
},
Boolean:function(value,index,parent){
return 'replaced-boolean';
},
Function:function(value,index,parent){
return value()
},
Number:function(value,index,parent){
return 'replaced-number';
},
String:function(value,index,parent){
return 'replaced-string';
},
Buffer:function(value,index,parent){
return value.toString()
}
}
}
jsonexport(contacts, options, function(err, csv){
console.log( csv )
});

@@ -288,6 +322,27 @@ ```

The output would be:
```
a,a2b
b,other field
x,replaced-number
z,bad ace
```
When using **typeHandlers**, Do NOT do this
```
lang,Hey - Node.js
module,Hey - jsonexport
var options={
typeHandlers:{
Object:function(value,index,parent){
return 'EVERYTHING IS AN OBJECT';
}
}
}
```
> It is NOT an error, however the recursive result becomes illegable functionality strings
## Contributors
- [Kauê Gimenes](https://github.com/kauegimenes)
- [Pierre Guillaume](https://github.com/papswell)
- [Acker Apple](https://github.com/AckerApple) [![hire me](https://ackerapple.github.io/resume/assets/images/hire-me-badge.svg)](https://ackerapple.github.io/resume/)
- [And many more...](https://github.com/kauegimenes/jsonexport/graphs/contributors)

@@ -10,2 +10,8 @@ /* jshint node:true */

const isRemoteTest = process.env.APPVEYOR || process.env.TRAVIS;
if( isRemoteTest ){
console.log('\x1b[34mRemote testing server detected on '+os.type()+' '+os.platform()+' '+os.release()+'\x1b[0m');
}
describe('Object', () => {

@@ -20,2 +26,3 @@ it('simple', () => {

});
it('complex', () => {

@@ -37,2 +44,77 @@ jsonexport({

});
});
it('Github #41 p1',()=>{
var contacts = [{
name: 'Bob',
lastname: 'Smith',
status: null,
test: true
},{
name: 'James',
lastname: 'David',
status: 'fired',
test: true
}];
jsonexport(contacts, (err, csv)=>{
expect(csv).to.equal(`name,lastname,status,test${os.EOL}Bob,Smith,,true${os.EOL}James,David,fired,true`);
});
});
it('Github #41 p2',()=>{
var contacts = {
'a' : 'another field',
'b' : '',
'c' : 'other field'
};
jsonexport(contacts, (err, csv)=>{
expect(csv).to.equal(`a,another field${os.EOL}b,${os.EOL}c,other field`);
});
});
it('Buffer to String - Github #48',()=>{
var contacts = {
'0' : true,
'1' : [11,22,33],
'2' : ()=>'bad ace',
'a' : Buffer.from('a2b', 'utf8'),
'b' : 'x',
'c' : 99,
'd' : {
x:Buffer.from('other field', 'utf8')
}
};
var options={
typeHandlers:{
Array:function(value,index,parent){
return 'replaced-array';
},
Boolean:function(value,index,parent){
return 'replaced-boolean';
},
Function:function(value,index,parent){
return value();
},
Number:function(value,index,parent){
return 'replaced-number';
},
String:function(value,index,parent){
return 'replaced-string';
},
Buffer:function(value,index,parent){
if(parent===contacts){
return 'parentless-'+index;
}
return value.toString();
}
}
};
jsonexport(contacts, options, (err, csv)=>{
expect(csv).to.equal(`0,replaced-boolean${os.EOL}1,replaced-array${os.EOL}2,bad ace${os.EOL}a,parentless-a${os.EOL}b,replaced-string${os.EOL}c,replaced-number${os.EOL}d.x,other field`);
});
});
});

@@ -175,3 +175,3 @@ var chai = require('chai');

});
describe('Handlers', () => {
describe.skip('Handlers', () => {
it('handleString', () => {

@@ -178,0 +178,0 @@ jsonexport({

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc