1

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.

1
  • So what problem are you having doing the conversation? Stackoverflow gets a lot of questions of the format "I have this data format, I want this different data format, I haven't shared any code at all" which are better suited to a site like fiverr.com Commented Nov 14, 2022 at 15:40

5 Answers 5

2

You can use Object.entries() combined with Array.prototype.reduce() and checking the typeof the values

  • Notice that solution expects data values are of type string and object

Code:

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).reduce((a, [k, v]) => {
  typeof v === 'object'
    ? Object.entries(data[k]).forEach(([n, v]) => (a[`${k}-${n}`] = v))
    : (a[k] = v)
  return a
}, {})

console.log(result)

Sign up to request clarification or add additional context in comments.

Comments

1

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)

Comments

0

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.

Comments

0

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);

Comments

0

Try this :

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

const finalObj = {};

Object.keys(obj).forEach(key => {
  if (typeof obj[key] === 'object') {
    Object.keys(obj[key]).forEach(innerObjKey => {
      finalObj[`${key}-${innerObjKey}`] = obj[key][innerObjKey]
    })
  } else {
    finalObj[key] = obj[key]
  }
});

console.log(finalObj);

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.