1

So I need a function that converts a js object of type:

{node: 'X', children: [{node: 'Y'}]}

with any depth into a string that is similar to html. For example the above should be converted into something like:

'<div class="X"><div class="Y"></div></div>'

This should be intuitive in a way that the order nodes are inserted into each other is same divs are. So here is what I have this far:

function convertObj(obj){
  const html_start = '<div class="';
  const html_end = '</div>';
  let current_parent = obj;
  let child_nodes = '';
  console.log(current_parent, current_parent.children)  
  if( typeof( current_parent.children)!= 'undefined'){
    let childrn = current_parent.children.map(child_node => convertObj(child_node) )
    child_nodes = child_nodes + childrn
  }
  return html_start+current_parent.node+'">'+child_nodes+html_end;
}

The problem is , between child nodes if they are multiple in number. And here is my jest test, which is failing

describe('convertObj', () => {
  it('should turn node value to a div with class of the same name', () => {
    expect(convertObj({node: 'A'})).toBe('<div class="A"></div>');
  });
  it('should incert nodes in children to parent node', () => {
    expect(convertObj({node: 'A', children:[{node : 'B'}]})).toBe('<div class="A"><div class="B"></div></div>');
    expect(convertObj({node: 'A', children:[{node : 'B'}, {node: 'C', children: [{node: 'D'}]}]})).toBe('<div class="A"><div class="B"></div> <div class="C"><div class="D"></div></div></div>');    
  });
}); 

Help appreciated! You can run tests here

3
  • Concatenating a string and an array will call .join() on the array. Replace the implicit call with an explicit one with the proper settings. Commented Jun 6, 2018 at 19:41
  • @JonathanEltgroth I feel like like I miss a small bit, and starting over with JQ seems redundant Commented Jun 6, 2018 at 19:42
  • @Andreas good point, that is what I was missing! Commented Jun 6, 2018 at 19:44

2 Answers 2

2

Using some more ES6 syntactic sugar like object destructuring and a template literal, you can make a very simple recursive implementation:

const convertObj = ({ node, children = [] }) =>
  `<div class="${node}">${children.map(convertObj).join(' ')}</div>`

const tree = {node: 'A', children:[{node : 'B'}, {node: 'C', children: [{node: 'D'}]}]}

console.log(convertObj(tree))

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

4 Comments

This is beautiful. Where are you peaple getting this knowledge from ...
@seethrough I do have links if you want to follow up on documentation for those language constructs.
sure, I would love to, the test is failing because there is a space between sister tags
@seethrough you have a space in the unit test you provided in the code block (expect(convertObj({node: 'A', children:[{node : 'B'}, {node: 'C', children: [{node: 'D'}]}]})).toBe('<div class="A"><div class="B"></div> <div class="C"><div class="D"></div></div></div>'); ), that's why I put a space in .join(' ')
2

The problem is caused by the implicit call of .join() when concatenating child_nodes (a string) and childrn (an array).

Just add an explicit .join() with a space as separator and your function works as expected

function convertObj(obj){
  const html_start = '<div class="';
  const html_end = '</div>';
  let current_parent = obj;
  let child_nodes = '';

  if( typeof( current_parent.children)!= 'undefined'){
    let childrn = current_parent.children.map(child_node => convertObj(child_node) )
    child_nodes = child_nodes + childrn.join(" ");
  }

  return html_start+current_parent.node+'">'+child_nodes+html_end;
}

[{node: 'A', children:[{node : 'B'}]}, {node: 'A', children:[{node : 'B'}, {node: 'C', children: [{node: 'D'}]}]}]
   .forEach(test => console.log(convertObj(test)));

1 Comment

The other guy happened to answer faster, but thank you anyway, I upwoted your answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.