0

How can I create a specific JSON object from some HTML?

Example

This is very well formatted HTML page (rendered from markdown). I want to create a JSON representation of the sections on the page.

So each "h2" is a title. Each h3, h4, or h5, that follows it is a subtitle

Given this HTML:

<h2><a href="#charts">Charts</a></h2>
<ul>...</ul>
<h5><a href="#third-party">Third Party</a></h5>
<ul>...</ul>
<h5><a href="#reusable-chart-frameworks">Reusable Chart Frameworks</a></h5>
<ul>...</ul>
<h2><a href="#maps">Maps</a></h2>
<h5><a href="#third-party-1">Third Party</h5>
...

Return this JSON:

[
  {
    "title": {
      "text": "Charts",
      "href": "#charts"
    }
    "subtitles": [
      {
        "text": "Third Party",
        "href": "#third-party"
      },
      {
        "text": "Reusable Chart Frameworks",
        "href": "#reusable-chart-frameworks"
      }
    ]
  },
  {
    "title": {
      "text": "Maps",
      "href": "#maps"
    },
    "subtitles": ]
      "text": "Third Party",
      "href": "#third-party-1"
    ]
  },
  ...
]

Solutions I've considered

Seems like something jQuery could help a lot with. If the items were nested it would be very easy to do $('h2').each(...) and just loop through each section, appending it to my JSON object. However there is no nesting here, just siblings. Any ideas?

1

2 Answers 2

1

One other solution is to map it:

var mappedJSON = $('h2').map(function() {
  var $selfA = $(this).children('a');
  var subtiles = $(this).nextUntil('h2').filter(':header').children('a').map(function() {
    return {
      "text": $(this).text(),
      "href": $(this).attr('href')
    }
  }).get();
  return {
    "title": {
      "text": $selfA.text(),
      "href": $selfA.attr('href')
    },
    "subtitles": subtiles
  };
}).get();

console.log(mappedJSON);
$('<pre/>').appendTo($('body').empty()).text(JSON.stringify(mappedJSON, null, "\t"));
pre {
  tab-size: 2;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<h2><a href="#charts">Charts</a></h2>
<ul>...</ul>
<h5><a href="#third-party">Third Party</a></h5>
<ul>...</ul>
<h5><a href="#reusable-chart-frameworks">Reusable Chart Frameworks</a></h5>
<ul>...</ul>
<h2><a href="#maps">Maps</a></h2>
<h5><a href="#third-party-1">Third Party</h5>

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

Comments

0

Here's a solution that just relies on jQuery's .nextUntil() function.

var sections = [];

var eTitles = $('article').find('h2');

$(eTitles).each(function(){
  var section = {
    "title": {
      "text": $(this).text(),
      "href": $(this).find('a').attr('href')
    },
    "subtitles": []
  }

  var eSubtitles = $(this).nextUntil('h2').filter('h3, h4, h5');

  $(eSubtitles).each(function(){
    var subtitle = {
      "text": $(this).text(),
      "href": $(this).find('a').attr('href')
    }

    section.subtitles.push(subtitle);
  });

  sections.push(section);
});

Comments

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.