TheGrimSilence
TheGrimSilence

Reputation: 47

TypeScript: loop through JSON and match against a given Array

I need to be able to loop through any JSON file and then compare it against any given array. So for example, if you gave it a package.json containing

{
  "name": "testy",
  "version": "0.1.0",
  "description": "Testy Westy",
  "main": "bin/testy",
  "repository": "https://github.com/testy/westy.git",
  "author": "Testy Westy",
  "license": "MIT",
  "private": false,
  "scripts": {},
  "engines": {
    "node": ">= 8",
    "yarn": ">= 1"
  },
  "dependencies": {
    "chalk": "^2.3.0",
    "commander": "^2.12.2",
    "inquirer": "^4.0.1",
    "ts-node": "^3.3.0",
    "typescript": "^2.6.2",
    "vorpal": "^1.12.0"
  },
  "devDependencies": {
    "@types/commander": "^2.11.0",
    "@types/inquirer": "^0.0.35",
    "@types/node": "^8.5.2",
    "tslint": "^5.8.0",
    "tslint-config-prettier": "^1.6.0"
  }
}

and an array:

const generalInfo = [
  'name',
  'version',
  'description',
  'repository',
  'author',
  'license',
  'private',
]

It would pull the given fields from JSON if it exists while ignoring missing fields without error. Being able to preserve both the key and value would be preferable.

An example of what I'm talking about:

const pkg = require('package.json')
const generalInfo = ['name','version','description', 'engines.test']

search(pkg, generalInfo)

Would return:

D:\Testy>ts-node app/testy.ts
name: testy
version: 0.1.0
description: Testy Westy

Warning: "engines.test" does not exist.

EDIT: I actually forgot to add what I did already try. Which does a minimal version of what I need. I don't need someone to write the code for me, I just need help expanding what I've done.

function search(object: any) {
  if (object instanceof Object) {
    for (const key in object) {
      if (object.hasOwnProperty(key)) {
        search(object[key])
        const element = object[key]
        console.log(Chalk.default.magentaBright(`${key}:`), element)
      }
    }
  }
}

This code iterates through an object, and simply logs the keys and values. I don't know how to only pull what I need based on an array.

Upvotes: 0

Views: 365

Answers (2)

user8897421
user8897421

Reputation:

You can pass a function to JSON.parse that will only allow keys that are in the array.

const result = JSON.parse(pkg, (k, v) =>
  !k || generalInfo.includes(k) ? v : undefined
);

const pkg = `{
  "name": "testy",
  "version": "0.1.0",
  "description": "Testy Westy",
  "main": "bin/testy",
  "repository": "https://github.com/testy/westy.git",
  "author": "Testy Westy",
  "license": "MIT",
  "private": false,
  "scripts": {},
  "engines": {
    "node": ">= 8",
    "yarn": ">= 1"
  },
  "dependencies": {
    "chalk": "^2.3.0",
    "commander": "^2.12.2",
    "inquirer": "^4.0.1",
    "ts-node": "^3.3.0",
    "typescript": "^2.6.2",
    "vorpal": "^1.12.0"
  },
  "devDependencies": {
    "@types/commander": "^2.11.0",
    "@types/inquirer": "^0.0.35",
    "@types/node": "^8.5.2",
    "tslint": "^5.8.0",
    "tslint-config-prettier": "^1.6.0"
  }
}`


const generalInfo = [
  'name',
  'version',
  'description',
  'repository',
  'author',
  'license',
  'private',
];

const result = JSON.parse(pkg, (k, v) =>
  !k || generalInfo.includes(k) ? v : undefined
);

console.log(result);


You could also create a Set out of the array for better performance.

const s = new Set(generalInfo);
const result = JSON.parse(pkg, (k, v) => !k || s.has(k) ? v : undefined);

const pkg = `{
  "name": "testy",
  "version": "0.1.0",
  "description": "Testy Westy",
  "main": "bin/testy",
  "repository": "https://github.com/testy/westy.git",
  "author": "Testy Westy",
  "license": "MIT",
  "private": false,
  "scripts": {},
  "engines": {
    "node": ">= 8",
    "yarn": ">= 1"
  },
  "dependencies": {
    "chalk": "^2.3.0",
    "commander": "^2.12.2",
    "inquirer": "^4.0.1",
    "ts-node": "^3.3.0",
    "typescript": "^2.6.2",
    "vorpal": "^1.12.0"
  },
  "devDependencies": {
    "@types/commander": "^2.11.0",
    "@types/inquirer": "^0.0.35",
    "@types/node": "^8.5.2",
    "tslint": "^5.8.0",
    "tslint-config-prettier": "^1.6.0"
  }
}`


const generalInfo = [
  'name',
  'version',
  'description',
  'repository',
  'author',
  'license',
  'private',
];

const s = new Set(generalInfo);

const result = JSON.parse(pkg, (k, v) =>
  !k || s.has(k) ? v : undefined
);

console.log(result);

Upvotes: 1

Slai
Slai

Reputation: 22876

The JSON.parse reviver can be used to find the key value pairs:

const j = '{"name":"testy","version":"0.1.0","description":"Testy Westy","main":"bin/testy","repository":"https://github.com/testy/westy.git","author":"Testy Westy","license":"MIT","private":false,"scripts":{},"engines":{"node":">= 8","yarn":">= 1"},"dependencies":{"chalk":"^2.3.0","commander":"^2.12.2","inquirer":"^4.0.1","ts-node":"^3.3.0","typescript":"^2.6.2","vorpal":"^1.12.0"},"devDependencies":{"@types/commander":"^2.11.0","@types/inquirer":"^0.0.35","@types/node":"^8.5.2","tslint":"^5.8.0","tslint-config-prettier":"^1.6.0"}}'

const generalInfo = { 'name': void 0, 'version': void 0, 'description': void 0, 
          'repository': void 0, 'author': void 0, 'license': void 0, 'private': void 0 }
                      
JSON.parse(j, (k, v) => k in generalInfo ? generalInfo[k] = v : v)

console.log(generalInfo)

Upvotes: 0

Related Questions