如何解析分组的json?

我有一个JSON结构:

{
 "2014": [
  "2014-01",
  "2014-02",
  "2014-03",
  ...
],
 "2015": [
  "2015-01",
  "2015-02",
  "2015-03",
  ...
]
}

...并且需要将该JSON解析为这样的HTML结构,不管有没有jQuery。

<select name="valueAA" id="valueAA">
    <optgroup label="2014">
        <option value="2014-01">Jan 2014</option>
        <option value="2014-02">Feb 2014</option>
        <option value="2014-03">Mar 2014</option>
                ...
    </optgroup>
    <optgroup label="2015">
        <option value="2015-01">Jan 2015</option>
        <option value="2015-02">Feb 2015</option>
        <option value="2015-03">Mar 2015</option>
                ...
    </optgroup>
</select>

谢谢!

You can do this with a bit of jQuery and moment.js for your date formatting:

fiddler

HTML:

<select id="dates"></select>

JS:

var object = {
    "2014": [
      "2014-01",
      "2014-02",
      "2014-03"
    ],
    "2015": [
        "2015-01",
        "2015-02",
        "2015-03"
    ]
};

var $select = $('#dates');

$.each(object, function(year, dates) {
    var $optgroup = $('<optgroup/>').attr('label', year);
    $.each(dates, function(key, date) {
        $optgroup.append( 
            $('<option/>')
                .val(date)
                .text( moment(date, 'YYYY-MM').format('MMM YYYY') )
        );
    });
    $select.append($optgroup);
});

Solution in javascript compatible with old browsers:

var data = {
  dataLabel: ['valueData']
};

(function() {
  'use strict';

  var label,
    value,
    // other variables
    select = document.createElement('select'),
    optgroup,
    option,
    date;

  select.id = 'valueAA';
  select.name = 'valueAA';

  for (label in data)
    if (data.hasOwnProperty(label)) {
      // what you want to do with labels
      optgroup = document.createElement('optgroup')
      optgroup.setAttribute('label', label);
      select.appendChild(optgroup);
      for (value in data[label])
        if (data[label].hasOwnProperty(value)) {
          // what you want to do with values
          date = new Date(value);
          option = document.createElement('option')
          option.setAttribute('value', value);
          optgroup.appendChild(option);
          optgroup.innerHTML = date.toDateString().replace(/^.*\s(.*).*\s.*\s(.*)$/, '$1 $2');
        }
    }

  window.console.log(select);
  document.body.appendChild(select);
}());

Using for...in

You can use For...in to loop the object keys.

var data = { dataLabel : [ 'valueData' ] },
    label,
    value;
// other variables

for (label in data) if (data.hasOwnProperty(label)) {
    // what you want to do with labels
    for (value in data[label]) if (data[label].hasOwnProperty(value)) {
        // what you want to do with values
    }
}

In order to create DOM elements you can use createElement and appendChild. This is how you add it to the script:

// other variables
var select = document.createElement('select'),
    optgroup,
    option,
    date;
select.id = 'valueAA';
select.name = 'valueAA';

create the <optgroup>

// what you want to do with labels
optgroup = document.createElement('optgroup')
optgroup.setAttribute('label', label);
select.appendChild(optgroup);

create the <option>

// what you want to do with values
date = new Date(value);
option = document.createElement('option')
option.setAttribute('value', value);
optgroup.appendChild(option);
optgroup.innerHTML = date.toDateString().replace(/^.*\s(.*).*\s.*\s(.*)$/,'$1 $2');
</div>

A pure Javascript solution:

var data = {
        "2014": [
            "2014-01",
            "2014-02",
            "2014-03"
        ],
        "2015": [
            "2015-01",
            "2015-02",
            "2015-03"
        ]
    };

void function () {
    var form = document.createElement('form'),
        select = document.createElement('select');

    select.id = 'valueAA';
    select.name = 'valueAA';
    Object.keys(data).map(Number).sort(function (a, b) { return a - b; }).forEach(function (k) {
        var optgroup = document.createElement('optgroup');
        optgroup.label = k;
        data[k].forEach(function (a) {
            var d = new Date(a),
                option = document.createElement('option'),
                MONTH = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];
            option.text = MONTH[d.getMonth()] + ' ' + d.getFullYear();
            option.value = a;
            optgroup.appendChild(option);
        });
        select.appendChild(optgroup);
    });
    form.appendChild(select);
    document.body.appendChild(form);
}();

</div>

use recursion:

var json = {
  "2014": [
    "2014-01",
    "2014-02",
    "2014-03"
  ],
  "2015": [
    "2015-01",
    "2015-02",
    "2015-03"
  ]
};

function loadSelect(data) {
  for (var key in data) {
    if (data[key].constructor == Array) {
      var optG = document.createElement('optgroup'); // optgroup creation
      
          optG.setAttribute('label', key); // setting the label on optgroup
      
      for(var i = 0; i < data[key].length; i++){ // loop over the each array
        var opt = document.createElement('option'); // create option
        opt.setAttribute("value", data[key][i]); // set the value attribute
        opt.innerHTML = data[key][i]; // apply the text of the option
        optG.appendChild(opt); // append the option in the optgroup
      }
      
      document.querySelector('#valueAA').appendChild(optG); // finally after iteration push the 
      //                                 optgroup with options to the select element.
      
      loadSelect(data[key]); // call it recursively.
    }
  }
}
loadSelect(json);
<select name="valueAA" id="valueAA">
</select>

</div>