简体   繁体   中英

How do I from a JSON object convert to form of elements?

I have a JSON object as {a: 1, b: 2, c: [4, 5, 6], d: {x: 7, y: 8, z: [9, 0]}} , how do I convert it to a form of elements?

I want to convert to this:

<input type="hidden" name="obj[a]" value="1"/>
<input type="hidden" name="obj[b]" value="2"/>
<input type="hidden" name="obj[c][]" value="4"/>
<input type="hidden" name="obj[c][]" value="5"/>
<input type="hidden" name="obj[c][]" value="6"/>
<input type="hidden" name="obj[d][x]" value="7"/>
<input type="hidden" name="obj[d][y]" value="8"/>
<input type="hidden" name="obj[d][z][]" value="9"/>
<input type="hidden" name="obj[d][z][]" value="0"/>

Any ideas?

These should do it:

with jQuery

var obj = { a: 1, b: 2, c: [4, 5, 6], d: { x: 7, y: 8, z: [9, 0] } };

function analyzer(o, trail) {
    if (!trail) trail = 'obj';
    for (var n in o) {
        var el = $('<input>', { type: 'hidden' });
        el.attr('name', trail + '[' + n + ']');
        if (typeof o[n] === 'number') {
            el.attr('value', o[n]);
            $('body').append(el);
        } else if (Array.isArray(o[n])) {
            el.attr('name',function(i,v) { return v + '[]'; });
            for (var i = 0; i < o[n].length; ++i) {
                el.clone().attr('value', o[n][i] ).appendTo('body');
            }
        } else {
            analyzer(o[n], trail + '[' + n + ']');
        }
    }
}
analyzer(obj);

JSFIDDLE DEMO

FYI, you can find a compatibility patch for Array.isArray at MDN.

Or you can use jQuery.isArray() instead.


jQuery reworked

You may prefer this a bit. It doesn't create an element, then clone it in the Array loop, but rather uses a little redundant code to create the elements.

function analyzer(o, trail) {
    if (!trail) trail = 'obj';
    for (var n in o) {
        if (typeof o[n] === 'number') {
            $('<input>', { type: 'hidden', name: trail + '[' + n + ']', value: o[n] })
                .appendTo( 'body' );
        } else if (Array.isArray(o[n])) {
            for (var i = 0; i < o[n].length; ++i) {
                $('<input>', { type: 'hidden', name: trail + '[' + n + '][]', value: o[n][i] })
                    .appendTo( 'body' );
            }
        } else {
            analyzer(o[n], trail + '[' + n + ']');
        }
    }
}

JSFIDDLE DEMO


with native DOM API

If you're having any performance issues, use the native API, and cache the DOM selection.

function analyzer(o, trail) {
    var el;
    if (!trail) trail = 'obj';
    for (var n in o) {
        if (typeof o[n] === 'number') {
            el = document.createElement('input');
            el.type = 'hidden';
            el.name = trail + '[' + n + ']';
            el.value = o[n];
            container.appendChild( el );
        } else if (Array.isArray(o[n])) {
            for (var i = 0; i < o[n].length; ++i) {
                el = document.createElement('input');
                el.type = 'hidden';
                el.name = trail + '[' + n + '][]';
                el.value = o[n][i];
                container.appendChild( el );
            }
        } else {
            analyzer(o[n], trail + '[' + n + ']');
        }
    }
}

JSFIDDLE DEMO

Doesn't require much more code, should work in all typically supported browsers, and should be very fast.


native API reworked to shorten

function analyzer(o, trail) {
    var el;
    if (!trail) trail = 'obj';
    for (var n in o) {
        (el = document.createElement('input')).type = 'hidden';
        el.name = trail + '[' + n + ']';
        if (typeof o[n] === 'number') {
            container.appendChild( el ).value = o[n];
        } else if (Array.isArray(o[n])) {
            el.name += '[]';
            for (var i = 0; i < o[n].length; ++i) {
                container.appendChild( el.cloneNode(false) ).value = o[n][i];
            }
        } else {
            analyzer(o[n], trail + '[' + n + ']');
        }
    }
}

JSFIDDLE DEMO

For a quick response -

Create a function that loops through objects. Use a for in loop to create a string to concatonate these inputs. Test if the value found for each object contains a primitive value , array or object`.

Eg Object.prototype.toString.call(val) === '[object Object]';

If it does, recursively call the function to extract the values from said found object / array

Here this does not give the code for creating the HTML, but what it does it create an object with two arrays. One contains the name and the other contains the value. Also, this will work no matter how deeply you nest your objects.

Array.prototype.isArray=true;//Not sure this is the best solution, but it seems to work

function parse(a){
  var b,c,i,obj={
    name:[],
    value:[]
  };
  for(x in a){
    b=a[x];
    if(b.isArray){
      for(i=0;i<b.length;i++){
        obj.name.push('['+x+'][]');
        obj.value.push(b[i]);
      }
    }
    else if(typeof b==='object'){
      var f=x;
      var d=parse(b);
      for(i=0;i<d.name.length;i++){
        d.name[i]='['+f+']'+d.name[i];
      }
      console.log(d.name);
      obj.name.push.apply(obj.name, d.name);
      obj.value.push.apply(obj.value, d.value);
    }
    else{
      obj.name.push('['+x+']');
      obj.value.push(b);
    }
  }
  return obj;
}
console.log(parse({a: 1, b: 2, c: [4, 5, 6], d: {x: 7, y: 8, z: [9, 0]}}));

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM