最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

Convert JSON to HTML in Javascript - Stack Overflow

programmeradmin0浏览0评论

I am trying to covert a JSON file to HTML using vanilla JavaScript. The way I approached it appears to be working but the code is not ideal.

What I am doing is checking to see if the value of the key is an object. If so, this is a new HTML tag. If not then this is a attribute for the tag.

The problem that I am having is that I don't know how to properly loop through an object and test these conditions without duplicating my code.

Can someone help me identify how I can better write this?

function createComponent(ponent, defaults, map) {


  Object.keys(defaults).forEach(function (level1) {
    if (typeof defaults[level1] === "object") {
      var tag = document.createElement(level1);
      Object.keys(defaults[level1]).forEach(function (level2) {
        if (typeof defaults[level1][level2] === "object") {
          tag.appendChild(document.createElement(level2));
            Object.keys(defaults[level1][level2]).forEach(function (level3) {
            if (typeof defaults[level1][level2][level3] === "object") {
                console.log(defaults[level1][level2][level3]);
               tag.appendChild(document.createElement(level3));
            }
          });
        }
      });
    }
  });
}
createComponent("textBox", textBoxDefaults, map);

Pseudo code:

Check defaults object, is there an object at this level? If so, create an HTML tag with the same Key name. Is there values that are not objects? If so, add attributes to the created tag using the key value pair. Stop diving deeper into the JSON when you don't find anymore objects.

Sample JSON

 textbox: {
      id: 1,
      name: "Text Box",
      tmprops: {
        cur: 0,
        min: 5000,
        visible: true,
      },
      tmctxlst: {
        version: "2",
        txttmctx: {
          alwysshw: false,
          name: "default"
        }
      },

Desired Output

 <textbox id="1" name="text box">
      <tmprops cur="0" min="5000" visible="true" />
      <tmctxlst version="2">
        <txttmctx alwysshow="false" name="default">
      </tmctxlst>
</textbox>

I am trying to covert a JSON file to HTML using vanilla JavaScript. The way I approached it appears to be working but the code is not ideal.

What I am doing is checking to see if the value of the key is an object. If so, this is a new HTML tag. If not then this is a attribute for the tag.

The problem that I am having is that I don't know how to properly loop through an object and test these conditions without duplicating my code.

Can someone help me identify how I can better write this?

function createComponent(ponent, defaults, map) {


  Object.keys(defaults).forEach(function (level1) {
    if (typeof defaults[level1] === "object") {
      var tag = document.createElement(level1);
      Object.keys(defaults[level1]).forEach(function (level2) {
        if (typeof defaults[level1][level2] === "object") {
          tag.appendChild(document.createElement(level2));
            Object.keys(defaults[level1][level2]).forEach(function (level3) {
            if (typeof defaults[level1][level2][level3] === "object") {
                console.log(defaults[level1][level2][level3]);
               tag.appendChild(document.createElement(level3));
            }
          });
        }
      });
    }
  });
}
createComponent("textBox", textBoxDefaults, map);

Pseudo code:

Check defaults object, is there an object at this level? If so, create an HTML tag with the same Key name. Is there values that are not objects? If so, add attributes to the created tag using the key value pair. Stop diving deeper into the JSON when you don't find anymore objects.

Sample JSON

 textbox: {
      id: 1,
      name: "Text Box",
      tmprops: {
        cur: 0,
        min: 5000,
        visible: true,
      },
      tmctxlst: {
        version: "2",
        txttmctx: {
          alwysshw: false,
          name: "default"
        }
      },

Desired Output

 <textbox id="1" name="text box">
      <tmprops cur="0" min="5000" visible="true" />
      <tmctxlst version="2">
        <txttmctx alwysshow="false" name="default">
      </tmctxlst>
</textbox>
Share Improve this question edited Jun 20, 2020 at 9:12 CommunityBot 11 silver badge asked May 18, 2020 at 22:02 BromoxBromox 7072 gold badges13 silver badges35 bronze badges 2
  • Sounds like you could do this with a recursive function... see if you can re-implement it using recursion. Also, if you could edit your post to include some example JSON and example desired output would be awesome! – marno11 Commented May 18, 2020 at 22:37
  • 1 Added sample JSON and Desired HTML output – Bromox Commented May 18, 2020 at 23:02
Add a ment  | 

2 Answers 2

Reset to default 5

I believe the easiest way to avoid code duplication here is with recursion, and it can basically look like this:

function createObjectComponent(json) {
  const ponent = document.createElement("div");
  for(const entry of Object.entries(json)) {
    if(Array.isArray(value)) {
      ponent.appendChild(createArrayComponent(value));
    } else if(typeof value === "object") {
      ponent.appendChild(createObjectComponent(value));
    } else {
      ponent.appendChild(createSimpleValueComponent(value));
    }
  }
  return ponent
}

here's a working example, with some minor css, it includes your own example and also an example of an array handling ponent:

const appDiv = document.getElementById('app');

const example1 = {
  foo: 1,
  bar: {
    id: 2,
    obj: {
      test: 2
    }
  },
  a: ["a", "b", 1, {
    a: 1
  }]
}

const example2 = {
  id: 1,
  name: "Text Box",
  tmprops: {
    cur: 0,
    min: 5000,
    visible: true,
  },
  tmctxlst: {
    version: "2",
    txttmctx: {
      alwysshw: false,
      name: "default"
    }
  }
}

appDiv.appendChild(createObjectComponent(example2));
appDiv.appendChild(createObjectComponent(example1));
appDiv.appendChild(createArrayComponent(example1.a));

function createObjectComponent(json) {
  const ponent = document.createElement("div");
  ponent.className = "obj-ponent";
  ponent.innerHTML += "{";

  for (const entry of Object.entries(json)) {
    ponent.appendChild(getComponentForEntry(entry));
  }

  ponent.innerHTML += "}";

  return ponent
}

function getComponentForEntry([key, value]) {
  const entryDiv = document.createElement("div");
  const keySpan = document.createElement("span");

  keySpan.className = "key-span";
  keySpan.innerText = key + ":";

  entryDiv.appendChild(keySpan);
  if (Array.isArray(value)) {
    entryDiv.appendChild(createArrayComponent(value));
  } else if (typeof value === "object") {
    entryDiv.appendChild(createObjectComponent(value));
  } else {
    entryDiv.appendChild(createSimpleValueComponent(value));
  }

  return entryDiv;
}

function createArrayComponent(array) {
  const list = document.createElement("ul");
  list.className = "array-ponent";
  list.innerHTML += "[";
  for (let i = 0; i < array.length; i++) {
    const item = array[i];
    const listItem = document.createElement("li");
    listItem.appendChild(getComponentForEntry([i, item]))
    list.appendChild(listItem);
  }

  list.innerHTML += "]";

  return list;
}

function createSimpleValueComponent(value) {
  const span = document.createElement("span");
  span.innerText = value;

  return span;
}
#app {
  font-family: monospace;
}

div.obj-ponent {
  margin: 8px;
  background-color: #e4e4e4;
  border-radius: 6px;
  max-width: 300px;
  padding: 4px 16px;
}

ul.array-ponent {
  margin: 8px;
  background-color: #e4e4e4;
  list-style-type: none;
  padding: 4px 16px;
  border-radius: 6px;
  max-width: 300px;
}

span.key-span {
  padding-left: 16px;
  margin-right: 8px;
  color: blueviolet
}

span {
  color: green
}
<div id="app"></div>

You'll need a recursion to solve this,

Basically we take current object & it's key as string, then we traverse the object in dfs fashion & make applicable children, we're ending by returning the tag to the outer element.

window.onload = function () {
  console.log(solve(item.textbox, "textbox"));
}

const item = {
  textbox: {
    id: 1,
    name: "Text Box",
    tmprops: {
      cur: 0,
      min: 5000,
      visible: true,
    },
    tmctxlst: {
      version: "2",
      txttmctx: {
        alwysshw: false,
        name: "default"
      }
    },
  }
}

function solve(obj, tagName) {
  const tag = document.createElement(tagName);
  const currentKeys = Object.keys(obj)

  currentKeys.forEach((attribute => {
    if (typeof obj[attribute] === "object") {
      tag.appendChild(solve(obj[attribute], attribute))
    } else {
      tag.setAttribute(attribute, obj[attribute]);
    }
  }))
  return tag;
}

Output:

<textbox id=​"1" name=​"Text Box">​
    <tmprops cur=​"0" min=​"5000" visible=​"true">​</tmprops>
    <tmctxlst version=​"2">​
        <txttmctx alwysshw=​"false" name=​"default">​</txttmctx>
    </tmctxlst>
</textbox>

发布评论

评论列表(0)

  1. 暂无评论