0

I saw this question here before (here and here) but still haven't seen any good solution. Since it was asked in 2011 I thought that I might try by myself :)

I need to convert the whole HTML structure into JSON.

Structure:

<body>
<div class="container">
    Lorem ipsum dolor
</div>
<h1>This is heading 1
    <div class="footer">
       tessssst
    </div>
</h1>
</body>

Desired JSON:

{
    "body": {
        "div": {
            "text": "Loremipsumdolor",
            "class": "container"
        },
        "h1": {
            "div": {
                "text": "tessssst",
                "class": "footer"
            }
        }
    }
}

Are there any nice methods to do that except for writing my vanilla code? Thanks.

Community
  • 1
  • 1
mrgoos
  • 1,294
  • 14
  • 26
  • 1
    That's invalid JSON. I'd suggest using some of the existing solutions (such as [JSONML](https://en.wikipedia.org/wiki/JsonML)). – Bergi Aug 19 '15 at 13:00
  • Oh sorry, I have edited the snippet – mrgoos Aug 19 '15 at 13:06
  • Notice that properties in a JSON object are inherently unordered - `h1` could come before `div` in your example. Also your format doesn't support multiple children with the same tag name, which would lead to duplicate property names. The array you started with was the right hunch. – Bergi Aug 19 '15 at 15:45
  • Yes. They will be in order when I'll put the in an array of objects as follows: http://jsbin.com/suhota/edit?html,js,output – mrgoos Aug 20 '15 at 09:09
  • Objects that only have a single, unknown key don't make much sense though. Rather use `{tagName: "div", content:[…]}` – Bergi Aug 20 '15 at 10:20
  • what's the advantage? It will cause the json output to be unnecessarily large. Instead of looking for a "tagName" called "div", why not just looking for "div"? – mrgoos Aug 20 '15 at 11:53
  • Because code is abstract. It doesn't look for divs, it does look for tagnames. If you'd know beforehand that it's a div, you wouldn't need to put that information in your json at all. – Bergi Aug 20 '15 at 12:04
  • My code will look for tags. Some tags will be interesting to me and others won't. Why can't I just look for the ones that I'm interested at, directly? When I'm looping through this JSON I know exatly what to look for. I'm putting it in JSON in order to send it to my server and perform some logic there, I thought that it would be better then just sending my HTML DOM string ($(document.body).html()). Am I missing something? – mrgoos Aug 20 '15 at 12:18
  • Hm, maybe for a lookup it may be beneficial, but in general it's still odd. You couldn't easily reconstruct the html from it for example. Btw, if you can choose the format and are not forced to use JSON, then you should *absolutely* use XML serialisation for the DOM. Nothing else. – Bergi Aug 20 '15 at 12:56
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/87504/discussion-between-mrgoos-and-bergi). – mrgoos Aug 20 '15 at 15:07

1 Answers1

0

Try utilizing $.map()

var res = {};
var elems = $.map($("body"), function(el, index) {
  res[el.tagName] = $(el).children().map(function(i, elem) {
    var obj = {};
    var name = elem.tagName;
    if (!$(elem).children().length) {
      obj[name] = {
        "text": elem.textContent,
        "class": elem.className
      };
    } else {
      var _elems = $.map($(elem).children(), function(val, key) {
        var _obj = {};
        _obj[val.tagName] = {
          "text": val.textContent,
          "class": val.className
        };
        return _obj
      });
      obj[name] = {
        "text": elem.textContent,
        "class": elem.className
      };
      _elems.forEach(function(v, k) {
        var _name = Object.keys(v)[0];
        obj[name][_name] = {
          "class": v[_name]["class"],
          "text": v[_name]["text"]
        }
      })
    }
    return obj
  }).get();
  return res
});

console.log(elems);

$("<pre />", {"text": JSON.stringify(elems, null, 2)})
.prependTo("body");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>

<body>
  <div class="container">
    Lorem ipsum dolor
  </div>
  <h1>This is heading 1
    <div class="footer">
       tessssst
    </div>
</h1>
</body>
guest271314
  • 1
  • 15
  • 104
  • 177