Skip to content

Commit

Permalink
Release v0.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
cNille committed Mar 9, 2024
1 parent db3cce3 commit 51ebdcd
Show file tree
Hide file tree
Showing 10 changed files with 3,833 additions and 40 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
node_modules
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# v0.1.3

- Bug: Handle different structure between items in array. E.g: [{a: true}, {b: true}]
- Feature: Show type of the value for each path. If multiple types, show separated by a `|`.
- Tests: Added tests to cover the basic cases.
49 changes: 41 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,9 @@ You can also pipe in JSON.

```bash
$ echo '{"a": [{"b": true}]}' | jfe
a
a[].b
.a: array
.a[]: object
.a[].b: boolean
```

# Examples
Expand All @@ -42,11 +43,17 @@ Given a JSON file like this:
"departments": [
{
"name": "Research",
"employees": 100
"employees": 10,
"isRemote": true
},
{
"name": "Engineering",
"employees": 80
"employees": "80",
"budget": null,
"manager": {
"name": "John Doe",
"title": "Engineering Manager"
}
}
]
}
Expand All @@ -56,14 +63,40 @@ Given a JSON file like this:
Running jfe on this file would produce output similar to the following:

```css
organization.name
organization.location
organization.departments[].name
orgrnization.departments[].employees
.organization: object
.organization.name: string
.organization.location: string
.organization.departments: array
.organization.departments[]: object
.organization.departments[].name: string
.organization.departments[].employees: number | string
.organization.departments[].isRemote: boolean
.organization.departments[].budget: null
.organization.departments[].manager: object
.organization.departments[].manager.name: string
.organization.departments[].manager.title: string
```

This output indicates that the JSON file contains fields for the organization's name and location, as well as an array of departments, each with its own name and number of employees.

# Roadmap

For future roadmap, features that could be implemented are;

- Show types in order of usage.
- Show enum if variation is small in type.
- Provide a "stat" command to show statistics about the values. Like most common strings (if enum), or min/max/average for numbers.

If you want to contribute with any of these, feel free to send a PR!

# Testing

Test files are included in `/test`. To run test:

```bash
npm test
```

# License

This project is licensed under the ISC License - see the LICENSE.md file for details.
33 changes: 6 additions & 27 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
#!/usr/bin/env node
const fs = require("fs");

const { processJson } = require("./jfe");
function usageInstructions() {
// Either path to file, or pipe JSON to stdin
console.log("Usage: ");
Expand All @@ -9,31 +9,6 @@ function usageInstructions() {
console.log('\techo \'{"a": [{"b": true}]}\' | jfe');
}

function summarizePaths(jsonObj, prefix = "", paths = []) {
if (Array.isArray(jsonObj)) {
// Handle arrays: Add "[]" to the path and process the first element (if exists)
if (jsonObj.length > 0) {
summarizePaths(jsonObj[0], `${prefix}[]`, paths);
}
} else if (typeof jsonObj === "object" && jsonObj !== null) {
Object.keys(jsonObj).forEach((key) => {
const path = `${prefix}${prefix ? "." : ""}${key}`;
paths.push(path);
summarizePaths(jsonObj[key], path, paths);
});
}
return paths;
}

function processJson(json) {
try {
const paths = summarizePaths(json);
console.log(paths.join("\n"));
} catch (error) {
console.error("Error processing JSON:", error.message);
}
}

function readFile(filePath) {
try {
const data = fs.readFileSync(filePath, "utf8");
Expand All @@ -46,7 +21,7 @@ function readFile(filePath) {
}

function parseStdin() {
return new Promise((resolve, reject) => {
return new Promise((resolve) => {
if (process.stdin.isTTY) {
usageInstructions();
process.exit(1);
Expand All @@ -73,3 +48,7 @@ async function main() {
}

main();

module.exports = {
processJson,
};
73 changes: 73 additions & 0 deletions jfe.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
function summarizePaths(jsonObj, prefix = "", paths = {}) {
if (Array.isArray(jsonObj)) {
// Handle arrays: Add "[]" to the path and process the first element (if exists)
if (jsonObj.length > 0) {
const path = `${prefix}[]`;
if (!!prefix) {
if (!paths[prefix]) {
paths[prefix] = [];
}
paths[prefix].push(jsonObj);
}
for (let i = 0; i < jsonObj.length; i++) {
summarizePaths(jsonObj[i], path, paths);
}
}
} else if (typeof jsonObj === "object" && jsonObj !== null) {
const path = `${prefix}`;
if (!!prefix) {
if (!paths[path]) {
paths[path] = [];
}
paths[path].push(jsonObj);
}
Object.keys(jsonObj).forEach((key) => {
const k = key.includes(" ") ? `"${key}"` : key;
summarizePaths(jsonObj[key], `${path}.${k}`, paths);
});
} else {
// base case: add the value to the path
if (!paths[prefix]) {
paths[prefix] = [];
}
paths[prefix].push(jsonObj);
}
return paths;
}

function pathsToLines(paths) {
const lines = [];
for (const path in paths) {
const values = paths[path];
const valueTypes = values.map((value) => {
if (Array.isArray(value)) {
return "array";
} else if (value === null) {
return "null";
} else {
return typeof value;
}
});
const uniqueValueTypes = [...new Set(valueTypes)];
const valueType =
uniqueValueTypes.length === 1
? uniqueValueTypes[0]
: `${uniqueValueTypes.join(" | ")}`;
lines.push(`${path}: ${valueType}`);
}
return lines;
}

function processJson(jsonObject) {
try {
const paths = summarizePaths(jsonObject);
const lines = pathsToLines(paths);
for (const line of lines) {
console.log(line);
}
} catch (error) {
console.error("Error processing JSON:", error.message);
}
}

module.exports = { summarizePaths, pathsToLines, processJson };
Loading

0 comments on commit 51ebdcd

Please sign in to comment.