1233

I need to serialize an object to JSON. I'm using jQuery. Is there a "standard" way to do this?

My specific situation: I have an array defined as shown below:

var countries = new Array();
countries[0] = 'ga';
countries[1] = 'cd';
...

and I need to turn this into a string to pass to $.ajax() like this:

$.ajax({
    type: "POST",
    url: "Concessions.aspx/GetConcessions",
    data: "{'countries':['ga','cd']}",
...
Zach
  • 539
  • 1
  • 4
  • 22
Herb Caudill
  • 50,043
  • 39
  • 124
  • 173
  • 22
    no one pointed out that `countries` is the name of a variable, not a key...that information would be lost when you try to serialize it. – mpen Jun 03 '11 at 01:24
  • 6
    Yeah.. needs to be JSON.stringify({countries:countries}) – Bodman Sep 03 '11 at 21:23
  • 2
    angular.js has: angular.fromJson and angular.toJson ... so if you're already using angular, which is awesome then woot – CommaToast Jan 08 '13 at 06:31
  • http://stackoverflow.com/questions/38408348/how-to-return-json-array-from-controller-and-display-in-jquery-success/38408411#38408411 – Suraj Roy Jul 16 '16 at 06:36

11 Answers11

1158

JSON-js - JSON in JavaScript.

To convert an object to a string, use JSON.stringify:

var json_text = JSON.stringify(your_object, null, 2);

To convert a JSON string to object, use JSON.parse:

var your_object = JSON.parse(json_text);

It was recently recommended by John Resig:

...PLEASE start migrating your JSON-using applications over to Crockford's json2.js. It is fully compatible with the ECMAScript 5 specification and gracefully degrades if a native (faster!) implementation exists.

In fact, I just landed a change in jQuery yesterday that utilizes the JSON.parse method if it exists, now that it has been completely specified.

I tend to trust what he says on JavaScript matters :)

All modern browsers (and many older ones which aren't ancient) support the JSON object natively. The current version of Crockford's JSON library will only define JSON.stringify and JSON.parse if they're not already defined, leaving any browser native implementation intact.

CertainPerformance
  • 356,069
  • 52
  • 309
  • 320
  • 15
    Good point @Mark0978. Just by way of explanation, the arguments to JSON.stringify are explained [here](https://developer.mozilla.org/En/Using_JSON_in_Firefox#Converting_objects_into_JSON). I've not seen a good usecase for the second parameter yet, but the last parameter is quite useful: it indicates how many spaces to use to indent with when formatting the JSON string. –  Feb 17 '11 at 20:32
  • 1
    Check the issues before using this solution: [https://github.com/douglascrockford/JSON-js/pull/13] Maybe safer is tweak this code create some JSON2 object and use it regardless the JSON support in the browser. – xmedeko Oct 04 '11 at 08:39
  • 1
    @pat, the 2nd, "replacer" arg is very useful for custom serialization of known objects. For example, I am serializing SVG elements using: `JSON.stringify(obj, function(key, val) { if (val instanceof SVGSVGElement) {return val.xml || new XMLSerializer().serializeToString(val);} return val;})` – Courtney Christensen Feb 16 '12 at 00:03
  • Crockford's code wasn't playing nice with some more complex jQuery selectors. When I commented out the Object.prototype modifications at the bottom of the file, it worked as expected. – Chris Sep 12 '12 at 15:43
  • I actually prefer JSON3. It has AMD/requireJS support plus it does not use eval which Crockform himself mentioned as "evil". https://github.com/bestiejs/json3 – Shital Shah Dec 07 '13 at 07:56
184

I've been using jquery-json for 6 months and it works great. It's very simple to use:

var myObj = {foo: "bar", "baz": "wockaflockafliz"};
$.toJSON(myObj);

// Result: {"foo":"bar","baz":"wockaflockafliz"}
Jay Taylor
  • 13,185
  • 11
  • 60
  • 85
  • 13
    +1 If you're already using jQuery, this is the way to go. JSON-js is great as a standalone library but this plugin seamlessly integrates JSON.stringify and JSON.parse with jQuery. It's a win-win. IMHO, this should be the accepted answer. – Evan Plaice Apr 20 '12 at 08:39
  • 7
    @EvanPlaice - What do you mean 'seammless integrates'. What do I gain by using jquery-json over JSON-js ? – ripper234 Dec 06 '12 at 09:42
  • 6
    @ripper234 I mean that it uses the native JSON.stringify/JSON.parse methods if they're available, if not it will fall back to it's own implementation. Basically, it's a polyfill for JSON serialization. The benefit is that you get client-side JSON serialization whether or not your user's browser supports it natively. – Evan Plaice Dec 07 '12 at 16:04
  • 1
    I've been looking for a IE6 JSON.stringify replacement and this is the only one working so far. I mean, including json.js manually works great but makes conflicts with jQuery "$" namespace. – matewka Jan 19 '13 at 02:07
  • 1
    @EvanPlaice, jquery-json is not a polyfill. It is a library that uses native functionality if available. Rather, JSON-js ([json2.js specifically](https://github.com/douglascrockford/JSON-js/blob/master/json2.js)) is a polyfill because it provides the same JSON object and API browsers provide, but does not clobber native functionality (which means modern browsers still get the high-performance native implementation). – Matthew Flaschen Jun 27 '14 at 19:36
101

Works on IE8+

No need for jQuery, use:

JSON.stringify(countries); 
ripper234
  • 222,824
  • 274
  • 634
  • 905
pestatije
  • 1,051
  • 1
  • 7
  • 2
47

I haven't used it but you might want to try the jQuery plugin written by Mark Gibson

It adds the two functions: $.toJSON(value), $.parseJSON(json_str, [safe]).

Imad Alazani
  • 6,688
  • 7
  • 36
  • 58
Tahir Akhtar
  • 11,385
  • 7
  • 42
  • 69
37

No, the standard way to serialize to JSON is to use an existing JSON serialization library. If you don't wish to do this, then you're going to have to write your own serialization methods.

If you want guidance on how to do this, I'd suggest examining the source of some of the available libraries.

EDIT: I'm not going to come out and say that writing your own serliazation methods is bad, but you must consider that if it's important to your application to use well-formed JSON, then you have to weigh the overhead of "one more dependency" against the possibility that your custom methods may one day encounter a failure case that you hadn't anticipated. Whether that risk is acceptable is your call.

Adam Bellaire
  • 108,003
  • 19
  • 148
  • 163
30

I did find this somewhere. Can't remember where though... probably on StackOverflow :)

$.fn.serializeObject = function(){
    var o = {};
    var a = this.serializeArray();
    $.each(a, function() {
        if (o[this.name]) {
            if (!o[this.name].push) {
                o[this.name] = [o[this.name]];
            }
            o[this.name].push(this.value || '');
        } else {
            o[this.name] = this.value || '';
        }
    });
    return o;
};
Boro
  • 7,913
  • 4
  • 43
  • 85
jamesmortensen
  • 33,636
  • 11
  • 99
  • 120
  • 6
    You found it here: http://stackoverflow.com/questions/1184624/serialize-form-to-json-with-jquery/1186309#1186309 – Marcello Nuccio Mar 11 '11 at 21:33
  • This doesn't actually serialize the object to a JSON string. – Jay Taylor Jun 01 '11 at 21:38
  • 4
    @pyrony - Go to a web form on a website, load in the Jquery code in the FB Console, and then run this: `var data = "" + $.toJSON($('form').serializeObject());`. data is now a JSON string. Afterwards, run this: `alert(typeof data);` It should alert "string". Then run this: `alert(data);`, you should see JSON text. Finally, go to http://jsonlint.com and paste in the JSON string. It should validate as `Valid JSON`. I'm not sure I understand what you mean as everything seems to point to this producing valid JSON. Thanks again. – jamesmortensen Jun 02 '11 at 01:51
  • I get `$.toJSON is not a function ` on my server, so I included `` – rubo77 Oct 01 '13 at 04:43
  • 1
    @rubo77 - I don't recall exactly why I was using jquery-json. This was posted over 2-3/4 years ago, and I think it was still cool to try and support IE7 and IE6 back then, which didn't have a built-in JSON parser. You can actually replace `$.toJSON` with `JSON.stringify` and get the same result without external dependencies, assuming you're only supporting modern browsers. Hope this helps! :) – jamesmortensen Oct 01 '13 at 06:43
  • Look out, IE8 does not support serializeArray – DigitalDesignDj Oct 12 '15 at 17:56
11

If you don't want to use external libraries there is .toSource() native JavaScript method, but it's not perfectly cross-browser.

Alfred
  • 21,058
  • 61
  • 167
  • 249
Kain Haart
  • 139
  • 1
  • 5
11

Yes, you should JSON.stringify and JSON.parse your Json_PostData before calling $.ajax:

$.ajax({
        url:    post_http_site,  
        type: "POST",         
        data:   JSON.parse(JSON.stringify(Json_PostData)),       
        cache: false,
        error: function (xhr, ajaxOptions, thrownError) {
            alert(" write json item, Ajax error! " + xhr.status + " error =" + thrownError + " xhr.responseText = " + xhr.responseText );    
        },
        success: function (data) {
            alert("write json item, Ajax  OK");

        } 
});
Ihor Patsian
  • 1,288
  • 2
  • 15
  • 25
bruce
  • 1,286
  • 11
  • 14
10

The best way is to include the polyfill for JSON object.

But if you insist create a method for serializing an object to JSON notation (valid values for JSON) inside the jQuery namespace, you can do something like this:

Implementation

// This is a reference to JSON.stringify and provides a polyfill for old browsers.
// stringify serializes an object, array or primitive value and return it as JSON.
jQuery.stringify = (function ($) {
  var _PRIMITIVE, _OPEN, _CLOSE;
  if (window.JSON && typeof JSON.stringify === "function")
    return JSON.stringify;

  _PRIMITIVE = /string|number|boolean|null/;

  _OPEN = {
    object: "{",
    array: "["
  };

  _CLOSE = {
    object: "}",
    array: "]"
  };

  //actions to execute in each iteration
  function action(key, value) {
    var type = $.type(value),
      prop = "";

    //key is not an array index
    if (typeof key !== "number") {
      prop = '"' + key + '":';
    }
    if (type === "string") {
      prop += '"' + value + '"';
    } else if (_PRIMITIVE.test(type)) {
      prop += value;
    } else if (type === "array" || type === "object") {
      prop += toJson(value, type);
    } else return;
    this.push(prop);
  }

  //iterates over an object or array
  function each(obj, callback, thisArg) {
    for (var key in obj) {
      if (obj instanceof Array) key = +key;
      callback.call(thisArg, key, obj[key]);
    }
  }

  //generates the json
  function toJson(obj, type) {
    var items = [];
    each(obj, action, items);
    return _OPEN[type] + items.join(",") + _CLOSE[type];
  }

  //exported function that generates the json
  return function stringify(obj) {
    if (!arguments.length) return "";
    var type = $.type(obj);
    if (_PRIMITIVE.test(type))
      return (obj === null ? type : obj.toString());
    //obj is array or object
    return toJson(obj, type);
  }
}(jQuery));

Usage

var myObject = {
    "0": null,
    "total-items": 10,
    "undefined-prop": void(0),
    sorted: true,
    images: ["bg-menu.png", "bg-body.jpg", [1, 2]],
    position: { //nested object literal
        "x": 40,
        "y": 300,
        offset: [{ top: 23 }]
    },
    onChange: function() { return !0 },
    pattern: /^bg-.+\.(?:png|jpe?g)$/i
};

var json = jQuery.stringify(myObject);
console.log(json);
jherax
  • 5,238
  • 5
  • 38
  • 50
10

It's basically 2 step process:

First, you need to stringify like this:

var JSON_VAR = JSON.stringify(OBJECT_NAME, null, 2); 

After that, you need to convert the string to Object:

var obj = JSON.parse(JSON_VAR);
Arsen Khachaturyan
  • 7,904
  • 4
  • 42
  • 42
7

One thing that the above solutions don't take into account is if you have an array of inputs but only one value was supplied.

For instance, if the back end expects an array of People, but in this particular case, you are just dealing with a single person. Then doing:

<input type="hidden" name="People" value="Joe" />

Then with the previous solutions, it would just map to something like:

{
    "People" : "Joe"
}

But it should really map to

{
    "People" : [ "Joe" ]
}

To fix that, the input should look like:

<input type="hidden" name="People[]" value="Joe" />

And you would use the following function (based off of other solutions, but extended a bit)

$.fn.serializeObject = function() {
var o = {};
var a = this.serializeArray();
$.each(a, function() {
    if (this.name.substr(-2) == "[]"){
        this.name = this.name.substr(0, this.name.length - 2);
        o[this.name] = [];
    }

    if (o[this.name]) {
        if (!o[this.name].push) {
            o[this.name] = [o[this.name]];
        }
        o[this.name].push(this.value || '');
    } else {
        o[this.name] = this.value || '';
    }
});
return o;
};
Tim Burkhart
  • 658
  • 6
  • 10