Unable to parse this text to a JSON object

Viewed 107

I have the following structure of info, that I need to convert into a JSON with properties and data. Originally its plain text, but I have converted it into an array to make it easier

 [ '# Server',
      'redis_version:5.0.5',
      'redis_git_sha1:00000000',
      'redis_git_dirty:0',
      'redis_build_id:7983a619928f1f2d',
      'redis_mode:standalone',
      'os:Linux 3.10.0-693.5.2.el7.x86_64 x86_64',
      'arch_bits:64',
      'multiplexing_api:epoll',
      'atomicvar_api:atomic-builtin',
      'gcc_version:6.3.0',
      'process_id:1',
      'run_id:1348856f2bcc8af5cfef205f1880fedb68602201',
      'tcp_port:6379',
      'uptime_in_seconds:10484766',
      'uptime_in_days:121',
      'hz:10',
      'configured_hz:10',
      'lru_clock:11364638',
      'executable:/data/redis-server',
      'config_file:/etc/redis.conf',
      '',
      '# Clients',
      'connected_clients:34',
      'client_recent_max_input_buffer:2',
      'client_recent_max_output_buffer:0',
      'blocked_clients:0',
      '',
      '# Memory',
      'used_memory:1568376',
      'used_memory_human:1.50M',
      'used_memory_rss:2768896',
      'used_memory_rss_human:2.64M',
      'used_memory_peak:5866848',
      'used_memory_peak_human:5.60M',
      'used_memory_peak_perc:26.73%',
      'used_memory_overhead:1406080',
      'used_memory_startup:791240',
      'used_memory_dataset:162296',
      'used_memory_dataset_perc:20.88%',
      'allocator_allocated:1571256',
      'allocator_active:2084864',
      'allocator_resident:5722112',
      'total_system_memory:33730531328',
      'total_system_memory_human:31.41G',
      'used_memory_lua:37888',
      'used_memory_lua_human:37.00K' ]

And im trying to parse it into something that looks like the below structure

{
  Server : { 
    redis_version : "5.0.5",
    redis_git_sha1: "00000000"
    ...
  },
 Clients: {
    connected_clientes: 54,
    client_recent_max_input_buffer: 2,
    ...
 }
 Memory: {
   used_memory: 1568376,
   used_memory_human: "1.50M"
   ...
 }
}

So far I have been able to create the subobjects

{ Server: {},
  Clients: {},
  Memory: {},
  Persistence: {},
  Stats: {},
  Replication: {},
  CPU: {},
  Cluster: {},
  Keyspace: {} }

Using this code where i managed to create the objects:

var obj = {};
    console.log(lines)
    for (let i in lines) {
        if (lines[i].includes("#")) {
            let prop = lines[i].toString()
            let propFormat = prop.substring(2)
            obj[propFormat] = {}
        } else if (!lines[i].includes("#") && lines[i] != "") {
            // console.log(lines[i])
        }
    }

But im stuck after that, can someone bring some light on how to continue?

5 Answers

I would use a forEach to loop through the array.

Then using .substring to check if it's a new 'key'; remember that key so you can add all the values, until the next key is found;

const data = [ '# Server', 'redis_version:5.0.5', 'redis_git_sha1:00000000', 'redis_git_dirty:0', 'redis_build_id:7983a619928f1f2d', 'redis_mode:standalone', 'os:Linux 3.10.0-693.5.2.el7.x86_64 x86_64', 'arch_bits:64', 'multiplexing_api:epoll', 'atomicvar_api:atomic-builtin', 'gcc_version:6.3.0', 'process_id:1', 'run_id:1348856f2bcc8af5cfef205f1880fedb68602201', 'tcp_port:6379', 'uptime_in_seconds:10484766', 'uptime_in_days:121', 'hz:10', 'configured_hz:10', 'lru_clock:11364638', 'executable:/data/redis-server', 'config_file:/etc/redis.conf', '', '# Clients', 'connected_clients:34', 'client_recent_max_input_buffer:2', 'client_recent_max_output_buffer:0', 'blocked_clients:0', '', '# Memory', 'used_memory:1568376', 'used_memory_human:1.50M', 'used_memory_rss:2768896', 'used_memory_rss_human:2.64M', 'used_memory_peak:5866848', 'used_memory_peak_human:5.60M', 'used_memory_peak_perc:26.73%', 'used_memory_overhead:1406080', 'used_memory_startup:791240', 'used_memory_dataset:162296', 'used_memory_dataset_perc:20.88%', 'allocator_allocated:1571256', 'allocator_active:2084864', 'allocator_resident:5722112', 'total_system_memory:33730531328', 'total_system_memory_human:31.41G', 'used_memory_lua:37888', 'used_memory_lua_human:37.00K' ];

// Result
let res = {};

// Remember latest prop
let latestProp = null;

// For each data entry
data.forEach((d) => {

    // Starting with #: new key
    const firstChar = d.substring(0, 1);
    if (firstChar === '#') {
        latestProp = d.substring(2);
        res[latestProp] = {};
    } else {
        // Add key-value
        let s = d.split(':');
        if (s.length > 1) {
            res[latestProp][s[0]] = s[1];
        }
    }
});

console.log(res);

My suggestion would be something like this:


//Declaring prop before the loop so that it isn't reset each iteration
let prop;
for(...) {
...
} else if (!lines[i].includes("#") && lines[i] != "") {
            let split = lines[i].split(":");
            let key = split[0];
            let value = split[1];
            obj[prop][key] = value
}

here is a working snippet using array.reduce , I also removed the "" values from the array

const tobeConverted= [ '# Server',
      'redis_version:5.0.5',
      'redis_git_sha1:00000000',
      'redis_git_dirty:0',
      'redis_build_id:7983a619928f1f2d',
      'redis_mode:standalone',
      'os:Linux 3.10.0-693.5.2.el7.x86_64 x86_64',
      'arch_bits:64',
      'multiplexing_api:epoll',
      'atomicvar_api:atomic-builtin',
      'gcc_version:6.3.0',
      'process_id:1',
      'run_id:1348856f2bcc8af5cfef205f1880fedb68602201',
      'tcp_port:6379',
      'uptime_in_seconds:10484766',
      'uptime_in_days:121',
      'hz:10',
      'configured_hz:10',
      'lru_clock:11364638',
      'executable:/data/redis-server',
      'config_file:/etc/redis.conf',
      '# Clients',
      'connected_clients:34',
      'client_recent_max_input_buffer:2',
      'client_recent_max_output_buffer:0',
      'blocked_clients:0',
      '# Memory',
      'used_memory:1568376',
      'used_memory_human:1.50M',
      'used_memory_rss:2768896',
      'used_memory_rss_human:2.64M',
      'used_memory_peak:5866848',
      'used_memory_peak_human:5.60M',
      'used_memory_peak_perc:26.73%',
      'used_memory_overhead:1406080',
      'used_memory_startup:791240',
      'used_memory_dataset:162296',
      'used_memory_dataset_perc:20.88%',
      'allocator_allocated:1571256',
      'allocator_active:2084864',
      'allocator_resident:5722112',
      'total_system_memory:33730531328',
      'total_system_memory_human:31.41G',
      'used_memory_lua:37888',
      'used_memory_lua_human:37.00K' ]
      
 let index = 0;
 let keys=[]
 const reducedObj=tobeConverted.reduce((a,c)=>{
   if(c.includes("#")){
    const  key= c.split("#")[1].trim()
    keys.push(key)
    index++;
    return {...a,[key]:{}}
  }else{
     const split =c.split(":")
     console.log(split)
     const subkey =split[0].trim()
     const subValue =split[1].trim()
     a[keys[index-1]][subkey] = subValue;
  }
  return a
 },{})
 
      

I think you can do something like this:

function parse (lines) {
  const result = {};
  let section;
  lines.forEach((line) => {
    if (line) {
      if (line.startsWith('# ')) {
        section = line.substring(2);
        result[section] = {};
      } else {
        const [prop, value] = line.split(':');
        result[section][prop] = value;
      }
    }
  });
  
  return result;
}
const textdata = [ '# Server', 'redis_version:5.0.5', 'redis_git_sha1:00000000', 'redis_git_dirty:0', 'redis_build_id:7983a619928f1f2d', 'redis_mode:standalone', 'os:Linux 3.10.0-693.5.2.el7.x86_64 x86_64', 'arch_bits:64', 'multiplexing_api:epoll', 'atomicvar_api:atomic-builtin', 'gcc_version:6.3.0', 'process_id:1', 'run_id:1348856f2bcc8af5cfef205f1880fedb68602201', 'tcp_port:6379', 'uptime_in_seconds:10484766', 'uptime_in_days:121', 'hz:10', 'configured_hz:10', 'lru_clock:11364638', 'executable:/data/redis-server', 'config_file:/etc/redis.conf', '', '# Clients', 'connected_clients:34', 'client_recent_max_input_buffer:2', 'client_recent_max_output_buffer:0', 'blocked_clients:0', '', '# Memory', 'used_memory:1568376', 'used_memory_human:1.50M', 'used_memory_rss:2768896', 'used_memory_rss_human:2.64M', 'used_memory_peak:5866848', 'used_memory_peak_human:5.60M', 'used_memory_peak_perc:26.73%', 'used_memory_overhead:1406080', 'used_memory_startup:791240', 'used_memory_dataset:162296', 'used_memory_dataset_perc:20.88%', 'allocator_allocated:1571256', 'allocator_active:2084864', 'allocator_resident:5722112', 'total_system_memory:33730531328', 'total_system_memory_human:31.41G', 'used_memory_lua:37888', 'used_memory_lua_human:37.00K' ];

const parsedObj = {};

for (data of textdata) {
    // checking for keys
    if (data.startsWith("#")) {
        parsedObj[data.split(" ")[1]] = {};
        continue;
    }
    
    if (Object.keys(parsedObj).length && data) {
        let lastKeyFound = Object.keys(parsedObj).pop();
        const [key, value] = data.split(':');
        parsedObj[lastKeyFound][key] = value
    }
}

// console.log(parsedObj)

// converting parsedObj to json
const textdataJson = JSON.stringify(parsedObj, null, 2)
console.log(textdataJson)
Related