added json2yaml
This commit is contained in:
commit
a7ed9d461a
|
@ -0,0 +1,73 @@
|
|||
JSON to YAML
|
||||
===
|
||||
|
||||
The purpose of this utility is to pretty-print JSON in the human-readable YAML object notation
|
||||
(ignore the misnomer, it's not a markup language at all)
|
||||
|
||||
You see, JSON is a proper subset of YAML, The difference is that YAML can use whitespace instead of syntax, which is more human-readable.
|
||||
Also, YAML supports comments.
|
||||
|
||||
So, for all the times you want to turn JSON int YAML (YML):
|
||||
|
||||
{
|
||||
"foo": "bar",
|
||||
"baz": [
|
||||
"qux",
|
||||
"quxx"
|
||||
],
|
||||
"corge": null,
|
||||
"grault": 1,
|
||||
"garply": true,
|
||||
"waldo": "false",
|
||||
"fred": "undefined"
|
||||
}
|
||||
|
||||
becomes
|
||||
|
||||
---
|
||||
foo: "bar"
|
||||
baz:
|
||||
- "qux"
|
||||
- "quxx"
|
||||
corge: null
|
||||
grault: 1
|
||||
garply: true
|
||||
waldo: "false"
|
||||
fred: "undefined"
|
||||
|
||||
Usage
|
||||
---
|
||||
|
||||
Specify a file:
|
||||
|
||||
json2yaml ./example.json
|
||||
|
||||
yaml2json ./example.kml | json2yaml
|
||||
|
||||
Or pipe from stdin:
|
||||
|
||||
curl -s http://foobar3000.com/echo/echo.json | json2yaml
|
||||
|
||||
wget -qO- http://foobar3000.com/echo/echo.json | json2yaml
|
||||
|
||||
Or require:
|
||||
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var YAML = require('json2yaml')
|
||||
, ymlText
|
||||
;
|
||||
|
||||
ymlText = YAML.stringify({
|
||||
"foo": "bar"
|
||||
, "baz": "corge"
|
||||
});
|
||||
|
||||
console.log(ymlText);
|
||||
}());
|
||||
|
||||
Installation
|
||||
---
|
||||
|
||||
npm install -g json2yaml
|
|
@ -0,0 +1,93 @@
|
|||
#!/usr/bin/env node
|
||||
(function () {
|
||||
"use strict";
|
||||
|
||||
var fs = require('fs')
|
||||
, filename = process.argv[2]
|
||||
, YAML = require('./index')
|
||||
;
|
||||
|
||||
/*
|
||||
*
|
||||
* Begin real handler
|
||||
*
|
||||
*/
|
||||
|
||||
function printUsage() {
|
||||
console.warn("Usages:");
|
||||
console.warn("json2yaml example.json");
|
||||
console.warn("cat example.json | json2yaml");
|
||||
}
|
||||
|
||||
function handleInput(err, text) {
|
||||
var data
|
||||
;
|
||||
|
||||
if (err) {
|
||||
printUsage();
|
||||
return;
|
||||
}
|
||||
|
||||
data = JSON.parse(text);
|
||||
console.info(YAML.stringify(data, null, ' '));
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* End real handler
|
||||
*
|
||||
*/
|
||||
|
||||
readInput(handleInput, filename);
|
||||
|
||||
//
|
||||
// this could (and probably should) be its own module
|
||||
//
|
||||
function readInput(cb, filename) {
|
||||
|
||||
function readFile() {
|
||||
fs.readFile(filename, 'utf8', function (err, text) {
|
||||
if (err) {
|
||||
console.error("[ERROR] couldn't read from '" + filename + "':");
|
||||
console.error(err.message);
|
||||
return;
|
||||
}
|
||||
|
||||
cb(err, text);
|
||||
});
|
||||
}
|
||||
|
||||
function readStdin() {
|
||||
var text = ''
|
||||
, timeoutToken
|
||||
, stdin = process.stdin
|
||||
;
|
||||
|
||||
stdin.resume();
|
||||
|
||||
// how to tell piping vs waiting for user input?
|
||||
timeoutToken = setTimeout(function () {
|
||||
cb(new Error('no stdin data'));
|
||||
stdin.pause();
|
||||
}, 1000);
|
||||
|
||||
stdin.on('data', function (chunk) {
|
||||
clearTimeout(timeoutToken);
|
||||
text += chunk;
|
||||
});
|
||||
|
||||
stdin.on('end', function () {
|
||||
cb(null, text);
|
||||
});
|
||||
}
|
||||
|
||||
if (filename) {
|
||||
readFile();
|
||||
}
|
||||
else {
|
||||
readStdin();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}());
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"foo": "bar",
|
||||
"baz": [
|
||||
"qux",
|
||||
"quxx"
|
||||
],
|
||||
"corge": null,
|
||||
"grault": 1,
|
||||
"garply": true,
|
||||
"waldo": "false",
|
||||
"fred": "undefined"
|
||||
}
|
|
@ -0,0 +1,10 @@
|
|||
---
|
||||
foo: bar
|
||||
baz:
|
||||
- qux
|
||||
- quxx
|
||||
corge: null
|
||||
grault: 1
|
||||
garply: true
|
||||
waldo: "false"
|
||||
fred: undefined
|
|
@ -0,0 +1,93 @@
|
|||
(function () {
|
||||
"use strict";
|
||||
|
||||
var typeOf = require('remedial').typeOf
|
||||
;
|
||||
|
||||
function stringify(data) {
|
||||
var handlers
|
||||
, indentLevel = ''
|
||||
;
|
||||
|
||||
handlers = {
|
||||
"undefined": function () {
|
||||
// objects will not have `undefined` converted to `null`
|
||||
// as this may have unintended consequences
|
||||
// For arrays, however, this behavior seems appropriate
|
||||
return 'null';
|
||||
}
|
||||
, "null": function () {
|
||||
return 'null';
|
||||
}
|
||||
, "number": function (x) {
|
||||
return x;
|
||||
}
|
||||
, "boolean": function (x) {
|
||||
return x ? 'true' : 'false';
|
||||
}
|
||||
, "string": function (x) {
|
||||
// to avoid the string "true" being confused with the
|
||||
// the literal `true`, we always wrap strings in quotes
|
||||
return JSON.stringify(x);
|
||||
}
|
||||
, "array": function (x) {
|
||||
var output = ''
|
||||
;
|
||||
|
||||
indentLevel = indentLevel.replace(/$/, ' ');
|
||||
x.forEach(function (y) {
|
||||
// TODO how should `undefined` be handled?
|
||||
var handler = handlers[typeOf(y)]
|
||||
;
|
||||
|
||||
if (!handler) {
|
||||
throw new Error('what the crap: ' + typeOf(y));
|
||||
}
|
||||
|
||||
output += '\n' + indentLevel + '- ' + handler(y);
|
||||
|
||||
});
|
||||
indentLevel = indentLevel.replace(/ /, '');
|
||||
|
||||
return output;
|
||||
}
|
||||
, "object": function (x) {
|
||||
var output = ''
|
||||
;
|
||||
|
||||
indentLevel = indentLevel.replace(/$/, ' ');
|
||||
Object.keys(x).forEach(function (k) {
|
||||
var val = x[k]
|
||||
, handler = handlers[typeOf(val)]
|
||||
;
|
||||
|
||||
if ('undefined' === typeof val) {
|
||||
// the user should do
|
||||
// delete obj.key
|
||||
// and not
|
||||
// obj.key = undefined
|
||||
// but we'll error on the side of caution
|
||||
return;
|
||||
}
|
||||
|
||||
if (!handler) {
|
||||
throw new Error('what the crap: ' + typeOf(val));
|
||||
}
|
||||
|
||||
output += '\n' + indentLevel + k + ': ' + handler(val);
|
||||
});
|
||||
indentLevel = indentLevel.replace(/ /, '');
|
||||
|
||||
return output;
|
||||
}
|
||||
, "function": function () {
|
||||
// TODO this should throw or otherwise be ignored
|
||||
return '[object Function]';
|
||||
}
|
||||
};
|
||||
|
||||
return '---' + handlers[typeOf(data)](data);
|
||||
}
|
||||
|
||||
module.exports.stringify = stringify;
|
||||
}());
|
|
@ -0,0 +1,21 @@
|
|||
{
|
||||
"author": "AJ ONeal <coolaj86@gmail.com> (http://coolaj86.info)",
|
||||
"name": "json2yaml",
|
||||
"description": "A commandline utility to convert JSON to YAML / YML",
|
||||
"keywords": ["yml", "yaml", "json", "cli", "util"],
|
||||
"version": "1.0.0",
|
||||
"main": "index.js",
|
||||
"bin": {
|
||||
"json2yaml": "./cli.js",
|
||||
"json2yml": "./cli.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">= 0.2.0"
|
||||
},
|
||||
"test": ["a", "b", "c"],
|
||||
"dependencies": {
|
||||
"remedial": "1.x"
|
||||
},
|
||||
"devDependencies": {},
|
||||
"preferGlobal": true
|
||||
}
|
|
@ -0,0 +1,13 @@
|
|||
#!/bin/bash
|
||||
|
||||
# npm install -g yaml2json
|
||||
node cli.js tests/object.json | yaml2json > /dev/null
|
||||
node cli.js tests/array.json | yaml2json > /dev/null
|
||||
# These tests would probably fail and seem a moot point to me
|
||||
# Why use YAML for literal values? It's general used for config
|
||||
# files will multiple teirs of data
|
||||
#node cli.js tests/string.json | yaml2json
|
||||
#node cli.js tests/number.json | yaml2json
|
||||
#node cli.js tests/boolean.json | yaml2json
|
||||
#node cli.js tests/null.json | yaml2json
|
||||
echo "Passed if no errors are listed above (and yaml2json is installed)"
|
|
@ -0,0 +1,22 @@
|
|||
[
|
||||
"baz",
|
||||
"qux",
|
||||
"quxx",
|
||||
null,
|
||||
true,
|
||||
{
|
||||
"foo": "bar",
|
||||
"corge": null,
|
||||
"grault": 1,
|
||||
"garply": true,
|
||||
"waldo": "false",
|
||||
"fred": "undefined"
|
||||
},
|
||||
[
|
||||
"hello",
|
||||
"world"
|
||||
],
|
||||
42,
|
||||
[
|
||||
]
|
||||
]
|
|
@ -0,0 +1,17 @@
|
|||
{
|
||||
"foo": "bar",
|
||||
"baz": [
|
||||
"qux",
|
||||
"quxx"
|
||||
],
|
||||
"corge": {
|
||||
"grault": 1,
|
||||
"garply": true,
|
||||
"waldo": "false",
|
||||
"fred": null
|
||||
},
|
||||
"empty": {
|
||||
},
|
||||
"hello": "world",
|
||||
"answer": 42
|
||||
}
|
Loading…
Reference in New Issue