admin管理员组

文章数量:1025202

I have a JSON:

    const json = {
  "name": "superman",
  "place": "universe",
  "pets": [
    {
      "id": "1",
      "type": "dog",
      "name": "Drogo"
    },
    {
      "id": "2",
      "type": "cat",
      "name": "Cindy"
    }
  ]
};

The requirement is to change this to a html string like so:

'<body><div>superman</div><div>universe</div><div><p>1</p><p>dog</p><p>Drogo</p><p>2</p><p>cat</p><p>Cindy</p></div></body>'

I wrote the below function to solve it. Basically I am iterating through json using Object.entries to obtain [key, value] pair and then appending the value to myStr, my final string variable. But I cannot retain the strings thus formed.

let myStr = ""; // initialize String
const printString = (o, myStr) => {
  if (typeof o === "string") {
    myStr += "<div>" + `${o}` + "</div><br>";
  }
  return myStr;
};
const getString = json => {
  for (let [key, value] of Object.entries(json)) {
    printString(value, myStr);
    if (Array.isArray(value)) {
      value.forEach(item => {
        printString(item, myStr);
      });
    }
  }
  return myStr;
};

const htmlString = "<body>" + getString(json) + "</body>";

console.log(htmlString);

I need some help with my logic. Further, I have a few issues:

i) How do I write 1 function that contains all of these features, including myStr variable, such that my code is modular ii) Why isn't myStr able to remember previous string? iii) In such type of problems, is it wise to just go through the specific json object and iterate through it or there should be a more generic function that checks for object, string or Array within the json and then generates string accordingly?

I have a JSON:

    const json = {
  "name": "superman",
  "place": "universe",
  "pets": [
    {
      "id": "1",
      "type": "dog",
      "name": "Drogo"
    },
    {
      "id": "2",
      "type": "cat",
      "name": "Cindy"
    }
  ]
};

The requirement is to change this to a html string like so:

'<body><div>superman</div><div>universe</div><div><p>1</p><p>dog</p><p>Drogo</p><p>2</p><p>cat</p><p>Cindy</p></div></body>'

I wrote the below function to solve it. Basically I am iterating through json using Object.entries to obtain [key, value] pair and then appending the value to myStr, my final string variable. But I cannot retain the strings thus formed.

let myStr = ""; // initialize String
const printString = (o, myStr) => {
  if (typeof o === "string") {
    myStr += "<div>" + `${o}` + "</div><br>";
  }
  return myStr;
};
const getString = json => {
  for (let [key, value] of Object.entries(json)) {
    printString(value, myStr);
    if (Array.isArray(value)) {
      value.forEach(item => {
        printString(item, myStr);
      });
    }
  }
  return myStr;
};

const htmlString = "<body>" + getString(json) + "</body>";

console.log(htmlString);

I need some help with my logic. Further, I have a few issues:

i) How do I write 1 function that contains all of these features, including myStr variable, such that my code is modular ii) Why isn't myStr able to remember previous string? iii) In such type of problems, is it wise to just go through the specific json object and iterate through it or there should be a more generic function that checks for object, string or Array within the json and then generates string accordingly?

Share Improve this question asked Sep 14, 2019 at 20:30 theusualtheusual 7913 gold badges11 silver badges28 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 2

Or, maybe, do it this way?

const json = {
  name: "superman",
  place: "universe",
  pets: [
    {
      id: "1",
      type: "dog",
      name: "Drogo"
    },
    {
      id: "2",
      type: "cat",
      name: "Cindy"
    }
  ]
};

function mkhtml(js){
  return Object.values(js).map(v=>
'<div>'+((typeof v)=='object'
   ?v.map(e=> '<p>'+Object.values(e).join('</p><p>')+'<p>').join('')
   :v)+'</div>').join('');
}
console.log(mkhtml(json));

And the same again, with conventional function syntax:

const json = {
  name: "superman",
  place: "universe",
  pets: [
    {
      id: "1",
      type: "dog",
      name: "Drogo"
    },
    {
      id: "2",
      type: "cat",
      name: "Cindy"
    }
  ]
};

function mkhtml(js){
  return Object.values(js).map(function(v){
    return '<div>'+((typeof v)=='object'
     ?v.map(function(e){return '<p>'+Object.values(e).join('</p><p>')+'<p>'}).join('')
     :v)+'</div>';
  }).join('');
}
console.log(mkhtml(json));

I just converted the last remaining arrow function to the "old" function form again.

The logic:

The outer .map() works on all the array Object.values() of the object that is stored in the variable json: for each value v a new <div> is created which is then filled with either the value v itself or a series of <p> elements in case v turns out to be an object (actually, it is an array of objects!) In this case the <p>s are filled with the values of each array element's object.

It looks a bit ugly but still works, If you know how deep your array is then I wouldn't go with recursion.

Working proof: https://jsfiddle/bajuck9y/

JS

let html = '';
for (const key in json) {
  if (!Array.isArray(json[key])) {
    html += '<div>' + json[key] + '</div>'
  } else {
    html += '<div>';
    for (const item of json[key]) {
      for (const key2 in item) {
        html += '<p>' + item[key2] + '</p>'
      }

    }
    html += '</div>';

  }

}

You were not adding the items in the property which was an array of Objects, you can use Object.values() to iterate over the values and append to the <p> tag.

Also you did not re-assign the new string formed in the printString() function back to the myStr variable, so as a result the new string that was generated was lost.

This is because string is immutable appending a new string to an older one will create a new instance of a string:

const json = {
  name: "superman",
  place: "universe",
  pets: [
    {
      id: "1",
      type: "dog",
      name: "Drogo"
    },
    {
      id: "2",
      type: "cat",
      name: "Cindy"
    }
  ]
};

let myStr = ""; // initialize String
const printString = (o, myStr, tag) => {
  if (typeof o === "string") {
    myStr += `<${tag}> ${o} </${tag}>`;
  }else if(typeof o === "object"){
    Object.values(o).forEach(val => myStr += `<${tag}> ${val} </${tag}>`);
  }
  return myStr;
};
const getString = json => {
  for (let [key, value] of Object.entries(json)) {
   if (Array.isArray(value)) {
      myStr += "<div>"
      value.forEach(item => {
        myStr = printString(item, myStr, "p");
      });
      myStr += "</div>"
   }else{
     myStr = printString(value, myStr, "div");
   }
  }
 return myStr;
};
const htmlString = "<body>" + getString(json) + "</body>";

console.log(htmlString);

If you want it to be more modular maybe you could split out your function into a number of small function helpers:

const json = {"name":"superman","place":"universe","pets":[{"id":"1","type":"dog","name":"Drogo"},{"id":"2","type":"cat","name":"Cindy"}]};

// Return a string given string and el args
const toEl = (str, el) => `<${el}>${str}</${el}>`;

// Call toEl with a string and 'div' param
const toDiv = (str) => toEl(str, 'div');

// Call toEl with a string and 'p' param
const toPara = (str) => toEl(str, 'p');

// Iterate over the array, and then
// iterate over each object calling getPara
// for each value
function getArr(arr) {
  return arr.map(obj => {
    return Object.values(obj).map(v => {
      return toPara(v);
    }).join('');
  }).join('');
}

// Now just join it all together
function getHTMLString(obj) {
  const name = toDiv(obj.name);
  const place = toDiv(obj.place);
  const pets = toDiv(getArr(obj.pets));
  return `<body>${name}${place}${pets}</body>`; 
}

console.log(getHTMLString(json));

I have a JSON:

    const json = {
  "name": "superman",
  "place": "universe",
  "pets": [
    {
      "id": "1",
      "type": "dog",
      "name": "Drogo"
    },
    {
      "id": "2",
      "type": "cat",
      "name": "Cindy"
    }
  ]
};

The requirement is to change this to a html string like so:

'<body><div>superman</div><div>universe</div><div><p>1</p><p>dog</p><p>Drogo</p><p>2</p><p>cat</p><p>Cindy</p></div></body>'

I wrote the below function to solve it. Basically I am iterating through json using Object.entries to obtain [key, value] pair and then appending the value to myStr, my final string variable. But I cannot retain the strings thus formed.

let myStr = ""; // initialize String
const printString = (o, myStr) => {
  if (typeof o === "string") {
    myStr += "<div>" + `${o}` + "</div><br>";
  }
  return myStr;
};
const getString = json => {
  for (let [key, value] of Object.entries(json)) {
    printString(value, myStr);
    if (Array.isArray(value)) {
      value.forEach(item => {
        printString(item, myStr);
      });
    }
  }
  return myStr;
};

const htmlString = "<body>" + getString(json) + "</body>";

console.log(htmlString);

I need some help with my logic. Further, I have a few issues:

i) How do I write 1 function that contains all of these features, including myStr variable, such that my code is modular ii) Why isn't myStr able to remember previous string? iii) In such type of problems, is it wise to just go through the specific json object and iterate through it or there should be a more generic function that checks for object, string or Array within the json and then generates string accordingly?

I have a JSON:

    const json = {
  "name": "superman",
  "place": "universe",
  "pets": [
    {
      "id": "1",
      "type": "dog",
      "name": "Drogo"
    },
    {
      "id": "2",
      "type": "cat",
      "name": "Cindy"
    }
  ]
};

The requirement is to change this to a html string like so:

'<body><div>superman</div><div>universe</div><div><p>1</p><p>dog</p><p>Drogo</p><p>2</p><p>cat</p><p>Cindy</p></div></body>'

I wrote the below function to solve it. Basically I am iterating through json using Object.entries to obtain [key, value] pair and then appending the value to myStr, my final string variable. But I cannot retain the strings thus formed.

let myStr = ""; // initialize String
const printString = (o, myStr) => {
  if (typeof o === "string") {
    myStr += "<div>" + `${o}` + "</div><br>";
  }
  return myStr;
};
const getString = json => {
  for (let [key, value] of Object.entries(json)) {
    printString(value, myStr);
    if (Array.isArray(value)) {
      value.forEach(item => {
        printString(item, myStr);
      });
    }
  }
  return myStr;
};

const htmlString = "<body>" + getString(json) + "</body>";

console.log(htmlString);

I need some help with my logic. Further, I have a few issues:

i) How do I write 1 function that contains all of these features, including myStr variable, such that my code is modular ii) Why isn't myStr able to remember previous string? iii) In such type of problems, is it wise to just go through the specific json object and iterate through it or there should be a more generic function that checks for object, string or Array within the json and then generates string accordingly?

Share Improve this question asked Sep 14, 2019 at 20:30 theusualtheusual 7913 gold badges11 silver badges28 bronze badges 0
Add a ment  | 

4 Answers 4

Reset to default 2

Or, maybe, do it this way?

const json = {
  name: "superman",
  place: "universe",
  pets: [
    {
      id: "1",
      type: "dog",
      name: "Drogo"
    },
    {
      id: "2",
      type: "cat",
      name: "Cindy"
    }
  ]
};

function mkhtml(js){
  return Object.values(js).map(v=>
'<div>'+((typeof v)=='object'
   ?v.map(e=> '<p>'+Object.values(e).join('</p><p>')+'<p>').join('')
   :v)+'</div>').join('');
}
console.log(mkhtml(json));

And the same again, with conventional function syntax:

const json = {
  name: "superman",
  place: "universe",
  pets: [
    {
      id: "1",
      type: "dog",
      name: "Drogo"
    },
    {
      id: "2",
      type: "cat",
      name: "Cindy"
    }
  ]
};

function mkhtml(js){
  return Object.values(js).map(function(v){
    return '<div>'+((typeof v)=='object'
     ?v.map(function(e){return '<p>'+Object.values(e).join('</p><p>')+'<p>'}).join('')
     :v)+'</div>';
  }).join('');
}
console.log(mkhtml(json));

I just converted the last remaining arrow function to the "old" function form again.

The logic:

The outer .map() works on all the array Object.values() of the object that is stored in the variable json: for each value v a new <div> is created which is then filled with either the value v itself or a series of <p> elements in case v turns out to be an object (actually, it is an array of objects!) In this case the <p>s are filled with the values of each array element's object.

It looks a bit ugly but still works, If you know how deep your array is then I wouldn't go with recursion.

Working proof: https://jsfiddle/bajuck9y/

JS

let html = '';
for (const key in json) {
  if (!Array.isArray(json[key])) {
    html += '<div>' + json[key] + '</div>'
  } else {
    html += '<div>';
    for (const item of json[key]) {
      for (const key2 in item) {
        html += '<p>' + item[key2] + '</p>'
      }

    }
    html += '</div>';

  }

}

You were not adding the items in the property which was an array of Objects, you can use Object.values() to iterate over the values and append to the <p> tag.

Also you did not re-assign the new string formed in the printString() function back to the myStr variable, so as a result the new string that was generated was lost.

This is because string is immutable appending a new string to an older one will create a new instance of a string:

const json = {
  name: "superman",
  place: "universe",
  pets: [
    {
      id: "1",
      type: "dog",
      name: "Drogo"
    },
    {
      id: "2",
      type: "cat",
      name: "Cindy"
    }
  ]
};

let myStr = ""; // initialize String
const printString = (o, myStr, tag) => {
  if (typeof o === "string") {
    myStr += `<${tag}> ${o} </${tag}>`;
  }else if(typeof o === "object"){
    Object.values(o).forEach(val => myStr += `<${tag}> ${val} </${tag}>`);
  }
  return myStr;
};
const getString = json => {
  for (let [key, value] of Object.entries(json)) {
   if (Array.isArray(value)) {
      myStr += "<div>"
      value.forEach(item => {
        myStr = printString(item, myStr, "p");
      });
      myStr += "</div>"
   }else{
     myStr = printString(value, myStr, "div");
   }
  }
 return myStr;
};
const htmlString = "<body>" + getString(json) + "</body>";

console.log(htmlString);

If you want it to be more modular maybe you could split out your function into a number of small function helpers:

const json = {"name":"superman","place":"universe","pets":[{"id":"1","type":"dog","name":"Drogo"},{"id":"2","type":"cat","name":"Cindy"}]};

// Return a string given string and el args
const toEl = (str, el) => `<${el}>${str}</${el}>`;

// Call toEl with a string and 'div' param
const toDiv = (str) => toEl(str, 'div');

// Call toEl with a string and 'p' param
const toPara = (str) => toEl(str, 'p');

// Iterate over the array, and then
// iterate over each object calling getPara
// for each value
function getArr(arr) {
  return arr.map(obj => {
    return Object.values(obj).map(v => {
      return toPara(v);
    }).join('');
  }).join('');
}

// Now just join it all together
function getHTMLString(obj) {
  const name = toDiv(obj.name);
  const place = toDiv(obj.place);
  const pets = toDiv(getArr(obj.pets));
  return `<body>${name}${place}${pets}</body>`; 
}

console.log(getHTMLString(json));

本文标签: javascriptconvert JSON object to html stringStack Overflow