Home > Enterprise >  How to transform only 2 properties but keep remaining same as is in a nested object structure?
How to transform only 2 properties but keep remaining same as is in a nested object structure?

Time:08-07

Apologies if title is not clear. I am using json2csv npm package to prepare csv from json object and this package allows us to add a hook to transform object before actual csv line is prepared.

I only need to manipulate two properties out of all. How can I do this effectively? My code feels too bloated.

const {
  Parser: Json2csvParser,
  transforms: { unwind },
} = require('json2csv');

const json2csvFields = [
  { value: 'root.filename', label: 'File Name' },
  { value: 'issue.root.priority', label: 'Priority' },
  { value: 'issue.root.url', label: 'URL' },
  { value: 'issue.root.startline', label: 'Start Line' },
  { value: 'issue.root.stopline', label: 'Stop Line' },
  { value: 'issue.root.startcolumn', label: 'Start Column' },
  { value: 'issue.root.stopcolumn', label: 'Stop Column' },
  { value: 'issue.root.issuename', label: 'Issue Name' },
  { value: 'issue.root.issuecategory', label: 'Issue Category' },
  { value: 'issue._', label: 'Issue Description' },
];

const sampleData = [
  {
    root: {
      filename:
        '/home/users/john-doe/workspace/foo-project/src/main/classes/foo.cls',
    },
    issue: {
      root: {
        priority: 1,
        url: 'www.example.com',
        startline: 100,
        stopline: 105,
        startcolumn: 20,
        stopcolumn: 25,
        issuename: 'blah',
        issuecategory: 'Category A',
      },
      _: '     Fox     ',
    },
  },
];

const json2csvOptions = {
  fields: json2csvFields,
  quote: '',
  header: true,
  transforms: [
    (item) => ({
      'root.filename': item.root.filename.replace(
        '/home/users/john-doe/workspace/foo-project/src/main/classes/',
        ''
      ),
      'issue._': `"${item.issue._.trim()}"`,
      // Except for the above two, everything else doens't need any transformation.
      'issue.root.priority': item.issue.root.priority,
      'issue.root.url': item.issue.root.url,
      'issue.root.startline': item.issue.root.startline,
      'issue.root.stopline': item.issue.root.stopline,
      'issue.root.startcolumn': item.issue.root.startcolumn,
      'issue.root.stopcolumn': item.issue.root.stopcolumn,
      'issue.root.issuename': item.issue.root.issuename,
      'issue.root.issuecategory': item.issue.root.issuecategory,
    }),
  ],
};

const json2csvParser = new Json2csvParser(json2csvOptions);

const csv = json2csvParser.parse(sampleData);
console.log(csv);

This prints below output:

File Name,Priority,URL,Start Line,Stop Line,Start Column,Stop Column,Issue Name,Issue Category,Issue Description
foo.cls,1,www.example.com,100,105,20,25,blah,Category A,"Fox"

EDIT: Updated code to a working example.

CodePudding user response:

After listing the two properties with special treatment, use Object.fromEntries and Object.entries to transform all the issue.root properties to their flat structure with .s in the property names. Then that object can be spread into the returned object.

const transformsFn = ({ root, issue }) => ({
  'root.filename': root.filename.replace(
    '/home/users/john-doe/workspace/foo-project/src/main/classes/',
    ''
  ),
  'issue._': `"${issue._.trim()}"`,
  ...Object.fromEntries(
    Object.entries(issue.root).map(
      ([key, val]) => [`issue.root.${key}`, val]
    )
  ),
});
const json2csvOptions = {
  fields: json2csvFields,
  quote: '',
  header: true,
  transforms: [transformsFn],
};
  • Related