You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
536 lines
11 KiB
Markdown
536 lines
11 KiB
Markdown
6 years ago
|
stringifier
|
||
|
================================
|
||
|
|
||
|
Yet another stringify function.
|
||
|
|
||
|
[![Build Status][travis-image]][travis-url]
|
||
|
[![NPM package][npm-image]][npm-url]
|
||
|
[![Bower package][bower-image]][bower-url]
|
||
|
[![License][license-image]][license-url]
|
||
|
|
||
|
|
||
|
DESCRIPTION
|
||
|
---------------------------------------
|
||
|
|
||
|
`stringifier` is a function like `JSON.stringify` but intended to be more customizable. For example,
|
||
|
|
||
|
- Max depth for recursive object tree traversal
|
||
|
- Per-type output customization
|
||
|
- Circular reference handling
|
||
|
|
||
|
|
||
|
Pull-requests, issue reports and patches are always welcomed. `stringifier` is a spin-off product of [power-assert](https://github.com/power-assert-js/power-assert) project.
|
||
|
|
||
|
|
||
|
API
|
||
|
---------------------------------------
|
||
|
|
||
|
|
||
|
### stringifier(options)
|
||
|
|
||
|
`require('stringifier')` exports single function `stringifier` that accepts `options` as optional parameters and returns configured function for stringify. This is the comprehensive usage.
|
||
|
|
||
|
```javascript
|
||
|
var stringifier = require('stringifier');
|
||
|
var stringify = stringifier(options);
|
||
|
console.log(stringify(anyVar));
|
||
|
```
|
||
|
|
||
|
|
||
|
### stringifier.stringify(val, options)
|
||
|
|
||
|
For more simplified usage, `stringifier` has a function `stringify`, that simply takes target object/value and returns stringified result string. `stringifier.stringify` accepts `options` as optional parameter too.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = require('stringifier').stringify;
|
||
|
console.log(stringify(anyVar));
|
||
|
```
|
||
|
|
||
|
|
||
|
INSTALL
|
||
|
---------------------------------------
|
||
|
|
||
|
### via npm
|
||
|
|
||
|
Install
|
||
|
|
||
|
$ npm install --save stringifier
|
||
|
|
||
|
Use
|
||
|
|
||
|
```javascript
|
||
|
var stringify = require('stringifier').stringify;
|
||
|
console.log(stringify(anyVar));
|
||
|
```
|
||
|
|
||
|
#### use stringifier npm module on browser
|
||
|
|
||
|
`stringifier` function is exported
|
||
|
|
||
|
<script type="text/javascript" src="./path/to/node_modules/stringifier/build/stringifier.js"></script>
|
||
|
|
||
|
|
||
|
### via bower
|
||
|
|
||
|
Install
|
||
|
|
||
|
$ bower install --save stringifier
|
||
|
|
||
|
Load (`stringifier` function is exported)
|
||
|
|
||
|
<script type="text/javascript" src="./path/to/bower_components/stringifier/build/stringifier.js"></script>
|
||
|
|
||
|
Use
|
||
|
|
||
|
```javascript
|
||
|
console.log(stringifier.stringify(anyVar));
|
||
|
```
|
||
|
|
||
|
|
||
|
EXAMPLE
|
||
|
---------------------------------------
|
||
|
|
||
|
For given context,
|
||
|
|
||
|
```javascript
|
||
|
var stringifier = require('stringifier'),
|
||
|
assert = require('assert');
|
||
|
|
||
|
function Student (name, age, gender) {
|
||
|
this.name = name;
|
||
|
this.age = age;
|
||
|
this.gender = gender;
|
||
|
}
|
||
|
|
||
|
var AnonStudent = function(name, age, gender) {
|
||
|
this.name = name;
|
||
|
this.age = age;
|
||
|
this.gender = gender;
|
||
|
};
|
||
|
|
||
|
var student = new Student('tom', 10, 'M');
|
||
|
var anonStudent = new AnonStudent('mary', 9, 'F');
|
||
|
|
||
|
var values = [
|
||
|
'string',
|
||
|
[null, undefined],
|
||
|
{
|
||
|
primitives: [true, false, -5, 98.6],
|
||
|
specific: {
|
||
|
regex: /^not/,
|
||
|
numbers: [NaN, Infinity, -Infinity]
|
||
|
},
|
||
|
userDefined: [
|
||
|
student,
|
||
|
anonStudent
|
||
|
]
|
||
|
}
|
||
|
];
|
||
|
```
|
||
|
|
||
|
|
||
|
#### default single-line output
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier();
|
||
|
console.log(stringify(values));
|
||
|
```
|
||
|
result:
|
||
|
|
||
|
```javascript
|
||
|
["string",[null,undefined],Object{primitives:[true,false,-5,98.6],specific:Object{regex:/^not/,numbers:[NaN,Infinity,-Infinity]},userDefined:[Student{name:"tom",age:10,gender:"M"},@Anonymous{name:"mary",age:9,gender:"F"}]}]
|
||
|
```
|
||
|
|
||
|
|
||
|
#### pretty printing with indentation
|
||
|
|
||
|
Use `indent` option for pretty printing. Using four spaces for indentation in this case.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({indent: ' '});
|
||
|
console.log(stringify(values));
|
||
|
```
|
||
|
|
||
|
result:
|
||
|
|
||
|
```javascript
|
||
|
[
|
||
|
"string",
|
||
|
[
|
||
|
null,
|
||
|
undefined
|
||
|
],
|
||
|
Object{
|
||
|
primitives: [
|
||
|
true,
|
||
|
false,
|
||
|
-5,
|
||
|
98.6
|
||
|
],
|
||
|
specific: Object{
|
||
|
regex: /^not/,
|
||
|
numbers: [
|
||
|
NaN,
|
||
|
Infinity,
|
||
|
-Infinity
|
||
|
]
|
||
|
},
|
||
|
userDefined: [
|
||
|
Student{
|
||
|
name: "tom",
|
||
|
age: 10,
|
||
|
gender: "M"
|
||
|
},
|
||
|
@Anonymous{
|
||
|
name: "mary",
|
||
|
age: 9,
|
||
|
gender: "F"
|
||
|
}
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
```
|
||
|
|
||
|
|
||
|
#### depth limitation
|
||
|
|
||
|
Use `maxDepth` option to stringify at most specified levels.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({maxDepth: 3, indent: ' '});
|
||
|
console.log(stringify(values));
|
||
|
```
|
||
|
|
||
|
result:
|
||
|
|
||
|
```javascript
|
||
|
[
|
||
|
"string",
|
||
|
[
|
||
|
null,
|
||
|
undefined
|
||
|
],
|
||
|
Object{
|
||
|
primitives: [
|
||
|
true,
|
||
|
false,
|
||
|
-5,
|
||
|
98.6
|
||
|
],
|
||
|
specific: Object{
|
||
|
regex: /^not/,
|
||
|
numbers: #Array#
|
||
|
},
|
||
|
userDefined: [
|
||
|
#Student#,
|
||
|
#@Anonymous#
|
||
|
]
|
||
|
}
|
||
|
]
|
||
|
```
|
||
|
|
||
|
|
||
|
#### anonymous class label
|
||
|
|
||
|
Use `anonymous` option to specify alternate type name for anonymous constructors.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({anonymous: 'ANON'});
|
||
|
assert(stringify(anonStudent) === 'ANON{name:"mary",age:9,gender:"F"}');
|
||
|
```
|
||
|
|
||
|
|
||
|
#### omit specific property from output
|
||
|
|
||
|
Customize `options.handlers`
|
||
|
|
||
|
```javascript
|
||
|
var stringify;
|
||
|
|
||
|
// property whitelist and reordering
|
||
|
stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.object(null, ['gender', 'age'])
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'Student{gender:"M",age:10}');
|
||
|
|
||
|
// blacklist by property name
|
||
|
stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.object(function (kvp) {
|
||
|
return ['age', 'gender'].indexOf(kvp.key) === -1;
|
||
|
})
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'Student{name:"tom"}');
|
||
|
|
||
|
// blacklist by property value
|
||
|
stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.object(function (kvp) {
|
||
|
return kvp.value !== 'M';
|
||
|
})
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'Student{name:"tom",age:10}');
|
||
|
|
||
|
// whitelist by property value
|
||
|
stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.object(function (kvp) {
|
||
|
return typeName(kvp.value) === 'string';
|
||
|
})
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'Student{name:"tom",gender:"M"}');
|
||
|
```
|
||
|
|
||
|
|
||
|
#### truncate property value
|
||
|
|
||
|
Return number from object predicate
|
||
|
|
||
|
```javascript
|
||
|
stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.object(function (kvp) {
|
||
|
if (kvp.key === 'name') {
|
||
|
return 3;
|
||
|
}
|
||
|
return true;
|
||
|
})
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'Student{name:"to..(snip),age:10,gender:"M"}');
|
||
|
```
|
||
|
|
||
|
|
||
|
|
||
|
CONFIGURATION
|
||
|
---------------------------------------
|
||
|
|
||
|
### options
|
||
|
|
||
|
|
||
|
#### options.maxDepth
|
||
|
Type: `number`
|
||
|
Default value: `null`
|
||
|
|
||
|
Max depth for recursive Object tree traversal
|
||
|
|
||
|
|
||
|
#### options.indent
|
||
|
Type: `String`
|
||
|
Default value: `null`
|
||
|
|
||
|
string value for indentation.
|
||
|
If this value is not empty, stringified result may contain multiple lines.
|
||
|
|
||
|
|
||
|
#### options.lineSeparator
|
||
|
Type: `String`
|
||
|
Default value: `'\n'`
|
||
|
|
||
|
string value for line-separator.
|
||
|
Makes sense only if `options.indent` is not empty.
|
||
|
|
||
|
|
||
|
#### options.anonymous
|
||
|
Type: `String`
|
||
|
Default value: `'@Anonymous'`
|
||
|
|
||
|
Type name string alternative for displaying Object created by anonymous constructor
|
||
|
|
||
|
|
||
|
#### options.circular
|
||
|
Type: `String`
|
||
|
Default value: `'#@Circular#'`
|
||
|
|
||
|
Alternative string for displaying Circular reference
|
||
|
|
||
|
|
||
|
#### options.snip
|
||
|
Type: `String`
|
||
|
Default value: `'..(snip)'`
|
||
|
|
||
|
For displaying truncated string
|
||
|
|
||
|
|
||
|
#### options.handlers
|
||
|
|
||
|
`options.handlers` is a object where property names are type names (string, number, ...) and values are per-type stringify strategy functions. Various strategies are defined in `stringifier.strategies`, and default strategies are defined as follows.
|
||
|
|
||
|
```javascript
|
||
|
var s = require('./strategies');
|
||
|
function defaultHandlers () {
|
||
|
return {
|
||
|
'null': s.always('null'),
|
||
|
'undefined': s.always('undefined'),
|
||
|
'function': s.prune(),
|
||
|
'string': s.json(),
|
||
|
'boolean': s.json(),
|
||
|
'number': s.number(),
|
||
|
'symbol': s.toStr(),
|
||
|
'RegExp': s.toStr(),
|
||
|
'String': s.newLike(),
|
||
|
'Boolean': s.newLike(),
|
||
|
'Number': s.newLike(),
|
||
|
'Date': s.newLike(),
|
||
|
'Array': s.array(),
|
||
|
'Object': s.object(),
|
||
|
'Error': s.object(null, ['message', 'code']),
|
||
|
'@default': s.object()
|
||
|
};
|
||
|
}
|
||
|
```
|
||
|
|
||
|
If unknown type is detected, strategy function registered by `'@default'` key will be used.
|
||
|
|
||
|
|
||
|
### strategies
|
||
|
|
||
|
For given `Student` pseudo-class and a `stringifier`,
|
||
|
|
||
|
```javascript
|
||
|
var stringifier = require('stringifier'),
|
||
|
s = stringifier.strategies,
|
||
|
assert = require('assert'),
|
||
|
|
||
|
function Student (name, age, gender) {
|
||
|
this.name = name;
|
||
|
this.age = age;
|
||
|
this.gender = gender;
|
||
|
}
|
||
|
|
||
|
var student = new Student('tom', 10, 'M');
|
||
|
```
|
||
|
|
||
|
#### always
|
||
|
|
||
|
`always` strategy always returns passed constant (In this case, `'foo'`).
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.always('foo')
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'foo');
|
||
|
```
|
||
|
|
||
|
#### json
|
||
|
|
||
|
`json` strategy applies `JSON.stringify` to input value then return the result string.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.json()
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === '{"name":"tom","age":10,"gender":"M"}');
|
||
|
```
|
||
|
|
||
|
#### toStr
|
||
|
|
||
|
`toStr` strategy calls `toString()` to input value then return the result string.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.toStr()
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === '[object Object]');
|
||
|
```
|
||
|
|
||
|
#### prune
|
||
|
|
||
|
`prune` strategy does not serialize target value but returns target type name surrounded by `#`.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.prune()
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === '#Student#');
|
||
|
```
|
||
|
|
||
|
#### newLike
|
||
|
|
||
|
`newLike` strategy emulates "new constructor call pattern".
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.newLike()
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'new Student({"name":"tom","age":10,"gender":"M"})');
|
||
|
```
|
||
|
|
||
|
#### object
|
||
|
|
||
|
`object` strategy stringifies target object recursively and decorate object literal-like syntax with its type name. `object` is a default strategy for objects, and any other unknown types.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Student': s.object()
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(student) === 'Student{name:"tom",age:10,gender:"M"}');
|
||
|
```
|
||
|
|
||
|
#### array
|
||
|
|
||
|
`array` strategy is an array specific stringification strategy, and is a default strategy for arrays.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Array': s.array()
|
||
|
}
|
||
|
});
|
||
|
assert(stringify(['foo', 'bar', 'baz']) === '["foo","bar","baz"]');
|
||
|
```
|
||
|
|
||
|
#### number
|
||
|
|
||
|
`number` strategy is a number specific stringification strategy, and is a default strategy for number. `number` strategy also provides `NaN`,`Infinity` and `-Infinity` handling.
|
||
|
|
||
|
```javascript
|
||
|
var stringify = stringifier({
|
||
|
handlers: {
|
||
|
'Array': s.array(),
|
||
|
'number': s.number()
|
||
|
}
|
||
|
});
|
||
|
assert(stringify([NaN, 0, Infinity, -0, -Infinity]) === '[NaN,0,Infinity,0,-Infinity]');
|
||
|
```
|
||
|
|
||
|
|
||
|
AUTHOR
|
||
|
---------------------------------------
|
||
|
* [Takuto Wada](https://github.com/twada)
|
||
|
|
||
|
|
||
|
LICENSE
|
||
|
---------------------------------------
|
||
|
Licensed under the [MIT](https://twada.mit-license.org/2014-2018) license.
|
||
|
|
||
|
|
||
|
[travis-url]: https://travis-ci.org/twada/stringifier
|
||
|
[travis-image]: https://secure.travis-ci.org/twada/stringifier.svg?branch=master
|
||
|
|
||
|
[npm-url]: https://npmjs.org/package/stringifier
|
||
|
[npm-image]: https://badge.fury.io/js/stringifier.svg
|
||
|
|
||
|
[bower-url]: https://badge.fury.io/bo/stringifier
|
||
|
[bower-image]: https://badge.fury.io/bo/stringifier.svg
|
||
|
|
||
|
[license-url]: https://twada.mit-license.org/2014-2018
|
||
|
[license-image]: https://img.shields.io/badge/license-MIT-brightgreen.svg
|