简体   繁体   中英

How to simplify JavaScript code modifying an JSON object

So the goal is to have included only those endpoints (and its methods eg get, post...) which are defined in the configuration file.

Example structure object that holds all the endpoints.

et swaggerApis = {
  header: {
    propertyHeader: "valueHeader"
  },
  blocks: [
    {
      tags: ["Tenant & User"],
      paths: {
        "/tenants": {
          post: {
            property: "value"
          },
          get: {
            property: "value"
          }
        },
        "/tenants/{id}": {
          post: {
            property: "value"
          },
          get: {
            property: "value"
          },
          delete: {
            property: "value"
          }
        }
      }
    }
  ]
};

Example of the configuration file that holds only those endpoints and its methods we want to have included in the final object.

const CONFIG = {
  api: {
    include: {
      "/tenants/{id}": ["get"]
    }
  }
};

So far here is my second version of the JavaScript code that works but introduces a high cyclometric complexity and is hard to read. I'm pretty new to JavaScript and looking a way not just to improve this code.

function includeEnpointsByConfig(data) {
  for (let blockItem of data.blocks) {
    for (let path in blockItem.paths) { //console.log(blockItem.paths[path])
      let result = setMethodsOfEndpoint(path, blockItem.paths[path]);
      if (result === 'undefined') {
        delete blockItem.paths[path] // if the config does not contain, remove
      } else {
        blockItem.paths[path] = result;
      }
    }
  }
  return data;
}

function setMethodsOfEndpoint(path, value) {
  let newMethods = {};

  for (let confPath in CONFIG.api.include) {
    if (path === confPath) { // match endpoint in config and swaggerApis object
      if (CONFIG.api.include[confPath].length > 0) { // if array in config is not empty , filter
        for (let c of CONFIG.api.include[confPath]) { //console.log(c); // get
          for (let v in value) {// properties of object tenants/{id} => {get{}, post{}}
            if (v === c) {
              newMethods = { ...newMethods, [v]: value[v] };
            }
          }
        }
      } else {// if array in config is empty , return param "value" from setMethodsOfEndpoint so we will include all methods of endpoint
        return value;
      }
  } else {
    return 'undefined'
  }
}
if (Object.keys(newMethods).length !==0) { // if in the config is in the array (nothing that match with swaggerEndpoints e.g. typo get --> gte)
  return newMethods
}  else {
  return value;
}
}

console.log(includeEnpointsByConfig(swaggerApis));

Code can be found also here https://codesandbox.io/s/blazing-worker-1emzl?file=/src/index2.js

I believe there is a way to do it much easier, cleaner and more effective. Thank you

With some creative usage of Array.prototype.forEach() , Object.keys() and Object.entries() :

swaggerApis.blocks.forEach(block => {
  Object.entries(block.paths).forEach(([path, methods]) => {
    if (!CONFIG.api.include[path]) {
      delete block.paths[path];
    } else {
      Object.keys(methods).forEach(method => {
        if (!CONFIG.api.include[path].includes(method)) {
          delete methods[method];
        }
      });
    }
  });
});

Complete snippet:

 const swaggerApis = { header: { propertyHeader: "valueHeader" }, blocks: [ { tags: ["Tenant & User"], paths: { "/tenants": { post: { property: "value" }, get: { property: "value" } }, "/tenants/{id}": { post: { property: "value" }, get: { property: "value" }, delete: { property: "value" } } } } ] }; const CONFIG = { api: { include: { "/tenants/{id}": ["get"] } } }; swaggerApis.blocks.forEach(block => { Object.entries(block.paths).forEach(([path, methods]) => { if (!CONFIG.api.include[path]) { delete block.paths[path]; } else { Object.keys(methods).forEach(method => { if (!CONFIG.api.include[path].includes(method)) { delete methods[method]; } }); } }); }); console.log(swaggerApis);

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM