0

I'm trying to use a JSON file to populate a web page. I am recursively looping through the object, writing the [key, value] properties to a string and using the 'list' property to increase the nesting level. I need it to be in order.

This is the function I've written:

function recurOBJ(my_obj){
    let x, str
    str = ``
    for( x in my_obj ){
        str += x + `: ` + my_obj[x].copy
        console.log(x);
        if ( my_obj[x].hasOwnProperty('list') ){
            recurOBJ(my_obj[x].list)
        }
    }
    console.log(str);
    return str
}

And this is a sample object:

{
    "item_01": {
        "copy": ["Some text."]
    },
    "item_02": {
        "copy": ["More text."],
        "list": {
            "listItem01": {
                "copy": ["List text."],
                "list": {
                        "item_a": { "copy": ["A: Lorem ipsum dolor sit amet."]},
                        "item_b": { "copy": ["B: Lorem ipsum dolor sit amet."]},
                        "item_c": { "copy": ["C: Lorem ipsum dolor sit amet."]},
                        "item_d": { "copy": ["D: Lorem ipsum dolor sit amet."]}
                }
        }}
    }
}

The problem is that when I'm looking at the console.log(x) output everything shows up in the correct order, but when the string is returned, console.log(str), it shows the nested values first and then the higher level items, ie. item01 and item02, after.

Correct => console.log(x):

item_01
item_02
listItem01
item_a
item_b
item_c
item_d

Incorrect => console.log(str):

item_a: A: Lorem ipsum dolor sit amet.
item_b: B: Lorem ipsum dolor sit amet.
item_c: C: Lorem ipsum dolor sit amet.
item_d: D: Lorem ipsum dolor sit amet.
listItem01: List text.
item_01: Some text.
item_02: More text.

I'm at a loss for how to remedy this. I've tried converting the Object to a Map to preserve the order, but that didn't work either.

xmattx
  • 133
  • 9

2 Answers2

1

So, you're doing everything right. Except that you should return the value of recursion too.

Change your code a little bit and it should work.

function recurOBJ(my_obj){
    let x, str
    str = ``
    for( x in my_obj ){
        str += x + ': ' + my_obj[x].copy + '\n'
        if ( my_obj[x].hasOwnProperty('list') ){
            str += recurOBJ(my_obj[x].list) + '\n'
        }
    }
    return str
}

output:

item_01: Some text.
item_02: More text.
listItem01: List text.
item_a: A: Lorem ipsum dolor sit amet.
item_b: B: Lorem ipsum dolor sit amet.
item_c: C: Lorem ipsum dolor sit amet.
item_d: D: Lorem ipsum dolor sit amet.
sertsedat
  • 3,490
  • 1
  • 25
  • 45
0

You could take a recursive approach by returning an array of strings and the children as well with list property or an empty object.

function getData(object) {
    return [].concat(
        ...Object
            .entries(object)
            .map(([k, v]) => [k + ': ' + v.copy[0], ...getData(v.list || {})])
    );
}

var data = { item_01: { copy: ["Some text."] }, item_02: { copy: ["More text."], list: { listItem01: { copy: ["List text."], list: { item_a: { copy: ["A: Lorem ipsum dolor sit amet."] }, item_b: { copy: ["B: Lorem ipsum dolor sit amet."] }, item_c: { copy: ["C: Lorem ipsum dolor sit amet."] }, item_d: { copy: ["D: Lorem ipsum dolor sit amet."] } } } } } };

console.log(getData(data));
.as-console-wrapper { max-height: 100% !important; top: 0; }
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392