Home > Software design >  Convert nested JSON to simple in JS
Convert nested JSON to simple in JS

Time:11-15

I want to convert a nested JSON like this

{
    "dateSession": "14/11/2022",
    "HRdata": {
        "1": 86,
        "2": 88,
        "3": 86,
        "4": 85
    },
    "SPO2data": {
        "1": 98,
        "2": 97,
        "3": 97,
        "4": 96
    }
}

to something like this:

{
    "dateSession": "14/11/2022",
    "HRdata-1": 86,
    "HRdata-2": 88,
    "HRdata-3": 86,
    "HRdata-4": 85,
    "SPO2data-1": 98,
    "SPO2data-2": 97,
    "SPO2data-3": 97,
    "SPO2data-4": 96,
}

where each fields in nested object will be named to field key which represents its actual path.

I want to generate a csv with all the data so first, I need a simple json to get arrays exported as well.

CodePudding user response:

You can do:

const data = {"dateSession": "14/11/2022","HRdata": {"1": 86,"2": 88,"3": 86,"4": 85},"SPO2data": {"1": 98,"2": 97,"3": 97,"4": 96}}

const result = {}
Object.entries(data)
  .filter(([k, v]) => typeof v !== 'object') 
  .forEach(([k, v]) => result[k] = v ) 
Object.keys(data)
  .filter(k => !(k in result))
  .map(
    k => Object
      .entries(data[k])
      .forEach(([n, v]) => result[`${k}-${n}`] = v)
  )

console.log(result)

CodePudding user response:

you would basically need to run your own parser and map out the keys manually. a recursive function should do the trick here where you're checking typeof key === 'object' && !Array.isArray(key) as the condition in order to recursively call back and map out the new/final object.

This is a REALLY quick/dirty/untested example...

let result = {};
const keysToMap = ['HRdata', 'SPO2data'];
let currKey = '';

const mapJson = (jsonData) => {
    const keys = Object.keys(jsonData);
    keys.forEach(key => {
        if (typeof jsonData[key] === 'object' && !Array.isArray(jsonData[key])) {
            currKey = key;
            mapJson(jsonData[key];
        } else {
            if (isNaN(key)) {
                result[key] = jsonData[currKey][key];
            } else {
              result[`${currKey}-${key}`] = jsonData[currKey][key];
            }
        }
    });
});

the above can be refactored in many BETTER WAYS, but this is the quickest i could come up with so i can get back to work lmfao.

again - the above is untested. its not perfect, but it gets the main idea across:

  • map out the object
  • have some way to identify that you're on a key that's gonna need to be flattened (this can be with a lookup, or some other more clever evaluation you might want to come up with)
  • when you run into a key that needs to be flattened, issue callback and let recursion do the work for you

The idea of my solution isn't for it to be pretty or performant, but to explain to you what you want to do just by glancing at it.

The main problem with the above is it doesn't handle more dimensions than you've laid out. if you want to do that, you'll have to re-evaluate the solution and do something better.

also, this is not a great O(n) solution either. i'm sure there are much better ones out there. but again - this just gets ya started so you can refactor to what you want for an end solution.

CodePudding user response:

const data = {
  dateSession: '14/11/2022',
  HRdata: {
    1: 86,
    2: 88,
    3: 86,
    4: 85,
  },
  SPO2data: {
    1: 98,
    2: 97,
    3: 97,
    4: 96,
  },
}

const flattenedData = {}
const flatten = (obj, oldName = '') => {
  //we are counting on the fact that we will get an object at first - you can add a condition to check it here
  const entries = Object.entries(obj)
  //iterate through the object. If we are encountering another object - send it again in recursion. If it's a value - add it to the flattened object
  for (const [key, value] of entries) {
    typeof value === 'object' && !Array.isArray(value)
      ? flatten(value, key   '-')
      : (flattenedData[oldName   key] = value)
  }
}

flatten(data)
console.log(flattenedData)

CodePudding user response:

I have written a recursive code for this conversion so that the highly nested objects also gets converted as per your requirement. The code is shown below:

const obj = {
    "dateSession": "14/11/2022",
    "HRdata": {
        "1": 86,
        "2": 88,
        "3": 86,
        "4": 85
    },
    "SPO2data": {
        "1": 98,
        "2": 97,
        "3": 97,
        "4": 96,
    }
};

let newObj = {};

function modifyJson(obj, newObj, count, upperKey) {
    for (const key of Object.keys(obj)) {
        if (typeof obj[key] === 'object') {
          newObj =  modifyJson(obj[key], newObj, count   1, key);
        } else if (count > 0) {
            newObj[`${upperKey}-${key}`] = obj[key];
        } else {
            newObj[key] = obj[key];
        }
    }
    return newObj;
}

newObj = modifyJson(obj, {}, 0, '');
console.log(newObj);
  • Related