Nov 18, 2010 at 6:06 PM

A little contribution for people, bored with all that "$().SPServices({operation: "GetListItems"... crap =)

(function($) {
	$.fn.SPServices.GetJSONListData = function(options) {
		var opt = $.extend({}, {
			relatedWebURL: "",		// [Optional] The name of the Web (site) which contains the related list
			listName: "",					// The name of the list which contains the additional information
			columns: [],					// An array of related columns to display
			CAMLQuery: "",				// [Optional] For power users, this CAML fragment will be <And>ed with the default query on the relatedList
			completefunc: null,		// Function to call on completion of rendering the change.
			debug: false					// If true, show error messages; if false, run silent
		}, options);
		if (opt.columns.length) {
			var cols = {};
			for(i = 0; i < opt.columns.length; i++) {
				cols[opt.columns[i]] = opt.columns[i];
			$.extend(opt, {columns : cols});

		var camlViewFields = "<ViewFields>";
		for (i = 0; i< opt.columns.length; i++){
			camlViewFields += '<FieldRef Name="' + opt.columns[i] + '" />';
		camlViewFields += "</ViewFields>";
		var data = {
			rows: []

				operation: "GetListItems",
				async: false,
				webURL: opt.relatedWebURL,
				listName: opt.listName,
				CAMLViewFields: camlViewFields ,
				CAMLQuery: opt.CAMLQuery ,
				CAMLQueryOptions: opt.CAMLQueryOptions ,
				CAMLRowLimit: 0,
				completefunc: function(xData, Status) {
					$(xData.responseXML).find("faultcode").each(function(index, item) {
						if (opt.debug) alert($(item).text());
					$(xData.responseXML).find("[nodeName=z:row]").each(function (index) {
						// parsing rows
						var c = {};
						for (var name in opt.columns) {
							c[name] = $(this).attr("ows_" + opt.columns[name]);
						data.rows.push(c); // and adding to array
					if(opt.completefunc != null) opt.completefunc(data);
		return data;

using is pretty straight and simple:

  var projData = $().SPServices.GetJSONListData({
    relatedWebURL: "/myWeb/",
    listName: "Projects", // don't forget - its list NAME, not an Url
    columns: ["ID", "Title"]

or, for example, with column mappings (here the "ID" column in SP list is mapped to "ProjectID" property of result row JSON object, and "Title" column mapped to "Name"):

  var projData = $().SPServices.GetJSONListData({
relatedWebURL: "/myWeb/",
listName: "Projects",
CAMLQuery: "<Query><Where><Eq><FieldRef Name='ParentCompany' /><Value Type='Lookup'>" + company + "</Value></Eq></Where></Query>",
columns: { ProjectID: "ID", Name: "Title" }


Nov 18, 2010 at 8:15 PM

Sweet! I take it the function would go in the spservices javascript? This is a nice addition. Does this handle memo fields as well?

Nov 18, 2010 at 8:53 PM

No. It totally misses any FieldType-dependant content parsing and treates everything as string.

It'ts pretty complex to use from such extension function all that content-parsing that built-in in SPServices. So I didnt even tried. This is enough for my needs and I just decided to share it in case if anyone wants to finish it and (maybe) include in SPServices itself.

Nov 19, 2010 at 2:04 AM
This is excellent! Now why haven't I already done this? I'll be digging into this idea, for sure. Thanks a lot for sharing it. M.
Nov 19, 2010 at 2:06 AM
This discussion has been copied to a work item. Click here to go to the work item and continue the discussion.
Nov 19, 2010 at 2:49 PM

I've been thinking abvout this some more. Can you guys give me some use cases for this? If I implement it, I want it to be of the widest possible use. What does this let you do that working with the XML in completefunc doesn't?


Nov 19, 2010 at 10:43 PM


     I think that for a lot of the things that I have been doing, this will just make the code shorter and somewhat easier to read. At least it seems to be easier. I have a lot of long functions where I have to do multiple

spservice calls in one function. This would appear to make it easier. It may also just be me, but it seems it would be slightly faster looping an array than trying to parse xml. I can do it either way, but it just seems cleaner

for what I do anyway.

Nov 20, 2010 at 8:26 AM

I was also thinking that this could really be used to support charting tools. I think that it would really be cool to incorporate charting functions and this just might help.

Nov 30, 2010 at 7:42 PM

Has anyone investigated whether using JSON vs the pure XML closes the response time gap?  This may make sense if the javascript object handling is faster than XML parsing...

Nov 30, 2010 at 7:47 PM

Since the Web Services return XML, we have to transform it to get JSON. So it can't be faster since we have to do that interim step. On the other hand, it depends on what you are going to do with the data from that point forward.


Nov 30, 2010 at 8:24 PM

Too bad - I suppose I was hoping this was a hereto undiscovered interface that would return native JSON objects.  Maybe in 2015 :)

Dec 5, 2010 at 3:32 PM
Edited Dec 5, 2010 at 3:36 PM

It could be added just as "outputformat" parameter in options, for example. It just simplifies using of returned data, abstracting you from all that XML-parsing crap and gives you a bit more ability to concentrate on functionality itself.

I've made it because I had too much very similar calls to "GetListItems" in my project and to keep original code unmodified I was forced to make this wrapper. I know that to be fully functional it requires some additional coding to parse different fieldtypes (I've added little code for lookup fields later) and it cannot be simple copied to all other service calls. But here, working with list item collections - it helps alot, really 8) For instance you can easily supply this result to jTemplates to populate formatted data to page:

var lookup = $.SPServices.GetJSONListData(...);
<script type="text/html" id="jt-lookup"><!--
{#foreach $T.rows as item}
<div class="jq-lookup-result-item ui-corner-all ui-widget-content" index="{$T.item$index}" spid="{$T.item.ID}">{$T.item$index}. {$T.item.Title} </div> 



Mar 4, 2011 at 10:07 PM
Edited Mar 4, 2011 at 10:18 PM

Wanted to follow-up on this topic - some interfaces such as the MIT SIMILE library of extensions like Timeline and Exhibit behave much better and are more reliable across browser platforms when you use things like JSON instead of XML.   The additional output format definitely simplifies development to the extent we put together our own:  To have something built in that spits out native JSON would be great.  All you need to do then is call the variable name or event sub-elements via variable.element.  Could be much easier than parsing the XML.

Jan 3, 2012 at 6:30 PM


I realize that you posted this code a really long time ago, but I wanted to thank you for it again. I'm finally getting to a JSON function for SPServices, as the requests have increased. If you're interested in following along, you can watch my blog:

I'm going to build an SPGetListItemsJson function once I have the SPXmlToJson function in good shape. You can check out the [very preliminary] documentation here: