├── ArrayCollection.cfc
├── ArrayCollection.md
├── DataTables.cfc
├── DataTables.md
├── README.md
└── docs
├── _config.yml
└── index.md
/ArrayCollection.cfc:
--------------------------------------------------------------------------------
1 | /**
2 | * @author Adrian J. Moreno
3 | * @website http://iknowkungfoo.com
4 | * @Twitter: @iknowkungfoo
5 | * @hint: A custom JSON render object for ColdFusion queries.
6 | * @Repo: https://github.com/iknowkungfoo/cfquery-to-json
7 | * @version 4.0
8 | * @requirements ColdFusion 9.0+ or Railo 4+
9 | * @BlogPost: http://cfml.us/Ce
10 | */
11 |
12 | component output="false" accessors="true" {
13 |
14 | /**
15 | * @required true
16 | * @setter false
17 | * @hint The query object to convert to JSON.
18 | */
19 | property query data;
20 | /**
21 | * @required false
22 | * @default "json"
23 | * @hint Sets the content-type for the response.
24 | */
25 | property string contentType;
26 | /**
27 | * @required false
28 | * @default true
29 | * @hint Prefix the content with keys.
30 | */
31 | property boolean dataHandle;
32 | /**
33 | * @required false
34 | * @default "data"
35 | * @hint The key for the data contained in the response.
36 | */
37 | property string dataHandleName;
38 | /**
39 | * @required false
40 | * @default true
41 | * @hint Return data as
42 | * true: an array of objects with data in name/value pairs
43 | * false: an array of arrays with data as unnamed elements
44 | * @example true: [{"id": 1, "value": "yes"}], false: [["1", "yes"]]
45 | */
46 | property boolean dataKeys;
47 | /**
48 | * @required false
49 | * @default false
50 | * @hint Data return formst, overrides dataHandle property.
51 | * true: return data content only, setDataHandle(false)
52 | * false: return standard data packet, setDataHandle(true)
53 | */
54 | property boolean dataOnly;
55 | /**
56 | * @required false
57 | * @default "lower"
58 | * @hint return data keys in "upper"- or "lower"-case.
59 | */
60 | property string dataKeyCase;
61 |
62 | /**
63 | * Setup JSON response packet.
64 | * @return ArrayCollection
65 | */
66 | public ArrayCollection function init() {
67 | variables.stData = {
68 | "success": true
69 | , "message": "Array Collection created."
70 | , "meta": {
71 | "offset": 0
72 | , "pageSize": 0
73 | , "totalRecords": 0
74 | }
75 | , "data": []
76 | };
77 | return this;
78 | }
79 |
80 | /**
81 | * Setup query object to convert with related data as needed.
82 | * @param required query data Query Object
83 | * @param numeric offset Query record offset
84 | * @param numeric pageSize Query record limit
85 | * @param numeric totalRecords Query total records is data set
86 | * @param boolean success
87 | * @param string message
88 | */
89 | public ArrayCollection function setData( required query data, numeric offset, numeric pageSize, numeric totalRecords, boolean success, string message ) {
90 | variables.data = arguments.data;
91 | variables.stData.meta["offset"] = structKeyExists(arguments, "offset") ? arguments.offset : 0;
92 | variables.stData.meta["pageSize"] = structKeyExists(arguments, "pageSize") ? arguments.pageSize : arguments.data.recordcount;
93 | variables.stData.meta["totalRecords"] = structKeyExists(arguments, "totalRecords") ? arguments.totalRecords : arguments.data.recordcount;
94 | structKeyExists(arguments, "message") ? setMessage(arguments.message) : setMessage("Array Collection populated.");
95 | if (structKeyExists(arguments, "success")) { setSuccess(arguments.success); }
96 | return this;
97 | }
98 |
99 | /**
100 | * Overrides the DataHandle property. Returns on the data array.
101 | * @param required boolean dataOnly
102 | */
103 | public ArrayCollection function setDataOnly(required boolean dataOnly ) {
104 | setDataHandle(!arguments.dataOnly);
105 | return this;
106 | }
107 |
108 | /**
109 | * Reset data to an empty query object.
110 | * @param required array columns Array of columns from original query object.
111 | */
112 | public ArrayCollection function resetData(required array columns) {
113 | setData(data: querynew(arrayToList(arguments.columns)));
114 | return this;
115 | }
116 |
117 | /**
118 | * Was the query successful or not?
119 | * @param required boolean success
120 | */
121 | public ArrayCollection function setSuccess(required boolean success) {
122 | variables.stData.success = arguments.success;
123 | return this;
124 | }
125 |
126 | /**
127 | * Set a message to be returned to the client.
128 | * @param required string message
129 | */
130 | public ArrayCollection function setMessage(required string message) {
131 | variables.stData.message = arguments.message;
132 | return this;
133 | }
134 |
135 | /**
136 | * Set other data in the meta object. Will not overwrite default keys.
137 | * @param required string key meta struct key
138 | * @param required any value meta struct key value
139 | */
140 | public ArrayCollection function setMetaKey(required string key, required any value) {
141 | if (!structKeyExists(variables.stData.meta, arguments.key)) {
142 | variables.stData.meta[arguments.key] = arguments.value;
143 | }
144 | return this;
145 | }
146 |
147 | /**
148 | * Change the existing columns names of the query object to a supplied array.
149 | * @param required array names Array of columns names, must match original column order and length
150 | * @return ArrayCollection
151 | */
152 | public ArrayCollection function changeColumnNames( required array names ) {
153 | if (!arrayIsEmpty(arguments.names)) {
154 | var aOriginalNames = getData().getColumnNames();
155 | if (arraylen(aOriginalNames) NEQ arrayLen(arguments.names)) {
156 | resetData(aOriginalNames)
157 | .setSuccess(false)
158 | .setMessage("Requested column names array length does not match the number of query columns.")
159 | .setMetaKey("originalNames", aOriginalNames)
160 | .setMetaKey("requestedNames", arguments.names);
161 | } else {
162 | getData().setColumnNames(arguments.names);
163 | }
164 | }
165 | return this;
166 | }
167 |
168 | /**
169 | * Render the collection data structure as JSON
170 | * @return json
171 | */
172 | public string function $renderdata() {
173 | var aData = [];
174 | if (getDataKeys()){
175 | aData = arrayOfStructs();
176 | } else {
177 | aData = arrayOfArrays();
178 | }
179 | if (getDataHandle()) {
180 | variables.stData[getDataHandleName()] = aData;
181 | return serializeJSON(variables.stData);
182 | } else {
183 | return serializeJSON(aData);
184 | }
185 | }
186 |
187 | /**
188 | * Returns the column list ordered alphabetically and in the case requested.
189 | * @return string
190 | */
191 | private string function getColumnList() {
192 | var columns = listSort( getData().columnlist, "textnocase" );
193 | if ( getDataKeyCase() IS "lower" ) {
194 | return lcase( columns );
195 | } else {
196 | return ucase( columns );
197 | }
198 | }
199 |
200 | /**
201 | * Convert n query object to an array of structs.
202 | * @return array
203 | */
204 | private array function arrayOfStructs() {
205 | var results = [];
206 | var temp = {};
207 | var q = getData();
208 | var rc = q.recordCount;
209 | var fields = listToArray(getColumnList());
210 | var fc = arrayLen(fields);
211 | var x = 0;
212 | var y = 0;
213 | var fieldName = "";
214 |
215 | for ( x = 1; x LTE rc; x++ ){
216 | temp = {};
217 | for ( y = 1; y LTE fc; y++ ) {
218 | fieldName = fields[y];
219 | temp[fieldName] = q[fieldName][x];
220 | }
221 | arrayAppend( results, temp );
222 | }
223 | return results;
224 | }
225 |
226 | /**
227 | * Convert a query object to an array of arrays.
228 | * @return array
229 | */
230 | private array function arrayOfArrays() {
231 | var results = [];
232 | var temp = [];
233 | var q = getData();
234 | var rc = q.recordCount;
235 | var fields = listToArray(getColumnList());
236 | var fc = arrayLen(fields);
237 | var x = 0;
238 | var y = 0;
239 |
240 | for ( x = 1; x LTE rc; x++ ) {
241 | temp = [];
242 | for ( y = 1; y LTE fc; y++ ) {
243 | arrayAppend( temp, q[fields[y]][x] );
244 | }
245 | arrayAppend( results, temp );
246 | }
247 | return results;
248 | }
249 |
250 | }
251 |
--------------------------------------------------------------------------------
/ArrayCollection.md:
--------------------------------------------------------------------------------
1 | ArrayCollection
2 | ===============
3 |
4 | A custom JSON render object for ColdFusion queries
5 |
6 | Details at blog post:
7 |
8 | http://iknowkungfoo.com/blog/index.cfm/2012/5/11/ArrayCollectioncfc-a-custom-JSON-renderer-for-ColdFusion-queries
9 |
10 | **Simple example**
11 |
12 | ```
13 |
14 |
15 |
16 |
17 | SELECT DISTINCT
18 | bookid,
19 | title,
20 | genre
21 | FROM
22 | books
23 | WHERE
24 | title LIKE
25 | ORDER BY
26 | genre, title
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 | ```
35 |
36 | **ColdBox Handler**
37 |
38 | ```
39 |
40 |
41 |
42 |
43 | ```
44 |
45 | **Output: Version 4**
46 | ```
47 | {
48 | "data": [
49 | {
50 | "bookid": 8,
51 | "genre": "Fiction",
52 | "title": "Apparition Man"
53 | },
54 | {
55 | "bookid": 2,
56 | "genre": "Non-fiction",
57 | "title": "Shopping Mart Mania"
58 | }
59 | ],
60 | "message": "Array Collection populated.",
61 | "meta": {
62 | "offset": 0,
63 | "pageSize": 2,
64 | "totalRecords": 2
65 | },
66 | "success": true
67 | }
68 | ```
69 |
70 | **New in Version 4**
71 |
72 | Refactored script CFC
73 |
74 | Added additional keys:
75 | * "message": String
76 | * "meta": object containing "offset", "pageSize" and "totalRecords"
77 | * "success": boolean
78 |
79 | If you trigger setDataOnly(true), the only the contents of the "data" key are returned.
80 |
81 | **Output: Versions 1 - 3**
82 | ```
83 | {
84 | "data": [
85 | {
86 | "bookid": 8,
87 | "genre": "Fiction",
88 | "title": "Apparition Man"
89 | },
90 | {
91 | "bookid": 2,
92 | "genre": "Non-fiction",
93 | "title": "Shopping Mart Mania"
94 | }
95 | ]
96 | }
97 | ```
98 |
99 | **New in Version 3**
100 |
101 | Converted to a script CFC
102 |
103 | Renamed queryToArrayOfStructs to arrayOfStructs.
104 |
105 | Renamed queryToArrayOfArrays to arrayOfArrays.
106 |
107 | Added the property "dataFormat" to convert between array or struct output.
108 |
109 | **New in Version 2**
110 |
111 | The function setDataKeys() triggers the return of an array of structs (true) or an array of arrays (false).
112 |
113 | The function setDataKeyCase() changes the column names (keys) in the structs from lowercase (default) to uppercase.
114 |
115 | **Depricated**
116 |
117 | The function setDataType() was replaced with setDataKeys().
118 |
--------------------------------------------------------------------------------
/DataTables.cfc:
--------------------------------------------------------------------------------
1 | /**
2 | *
3 | * @author Adrian J. Moreno
4 | * @email amoreno@iknowkungfoo.com
5 | * @description Custom JSON renderer used to convert CFML application queries for use with jQuery DataTables.
6 | * @version 3.0
7 | * @requirements ColdFusion 9.0+ or Railo 4+
8 | * @Repo: https://github.com/iknowkungfoo/cfquery-to-json
9 | *
10 | */
11 |
12 | component output="false" extends="ArrayCollection" accessors="true" {
13 |
14 | property type="numeric" name="echo" default="-1";
15 | property type="numeric" name="totalRecords" default="0";
16 | property type="numeric" name="totalDisplayRecords" default="0";
17 |
18 | public DataTables function init() {
19 | setContentType("json");
20 | setDataHandle(false);
21 | setDataFormat("array");
22 | setDataKeyCase("lower");
23 | setEcho(-1);
24 | setTotalRecords(0);
25 | setTotalDisplayRecords(0);
26 | return this;
27 | }
28 |
29 | public void function setData( required query data ){
30 | variables.data = arguments.data;
31 | if (structKeyExists(arguments.data, "total_records")){
32 | setTotalRecords( val(arguments.data.total_records) );
33 | setTotalDisplayRecords( val(arguments.data.total_records) );
34 | } else {
35 | setTotalRecords( arguments.data.recordcount );
36 | setTotalDisplayRecords( arguments.data.recordcount );
37 | }
38 |
39 | }
40 |
41 | public string function $renderdata(){
42 | var rs = {};
43 | if (getEcho() GTE 0) {
44 | rs["sEcho"] = val(getEcho());
45 | }
46 | if (getTotalRecords() GT 0) {
47 | rs["iTotalRecords"] = getTotalRecords();
48 | }
49 | if (getTotalDisplayRecords() GT 0) {
50 | rs["iTotalDisplayRecords"] = getTotalDisplayRecords();
51 | }
52 | if (getDataFormat() IS "array") {
53 | rs["aaData"] = arrayOfArrays();
54 | } else {
55 | rs["aaData"] = arrayOfStructs();
56 | }
57 | return serializeJSON(rs);
58 | }
59 | }
60 |
--------------------------------------------------------------------------------
/DataTables.md:
--------------------------------------------------------------------------------
1 | DataTables.cfc
2 | ===============
3 |
4 | A custom JSON render object to convert ColdFusion queries for use with [jQuery DataTables](http://datatables.net/).
5 |
6 | Requires ArrayCollection.cfc from this repo.
7 |
8 | More example code can be found in the [KungFooGallery ColdBox Applicaiton](https://github.com/iknowkungfoo/KungFooGallery-Simple-ColdBox).
9 |
10 | **Simple Example**
11 | ```
12 |
13 |
14 |
15 |
16 | SELECT
17 | a.artist_id,
18 | a.first_name,
19 | a.last_name,
20 | b.artwork_id,
21 | b.title,
22 | b.img_thumb
23 | FROM
24 | ARTISTS a
25 | INNER JOIN
26 | ARTWORK b ON b.artist_id = a.artist_id
27 |
28 | WHERE a.artist_id =
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | ```
38 |
39 | **Output**
40 | ```
41 | {
42 | "iTotalDisplayRecords": 16,
43 | "iTotalRecords": 16,
44 | "aaData": [
45 | [1, 1, "Doug", "8318007055_fa1c3dc930_t.jpg", 88888, "Flower"],
46 | [1, 2, "Doug", "2808827891_223469fd22_t.jpg", 88888, "Yellow flowers"],
47 | [1, 3, "Doug", "3086318277_8ee7912476_t.jpg", 88888, "Passion flower"],
48 | [1, 4, "Doug", "3575863689_f88082c56d_t.jpg", 88888, "Ouch"],
49 | [1, 5, "Doug", "3428958441_426d432137_t.jpg", 88888, "Yellow"],
50 | [1, 6, "Doug", "3495905775_b54f784b73_t.jpg", 88888, "Little yellow"],
51 | [1, 7, "Doug", "3067955110_aab017ef9a_t.jpg", 88888, "Burn Baby Burn"],
52 | [1, 8, "Doug", "4524800461_30334688bb_t.jpg", 88888, "Earth laughs in Flowers"],
53 | [1, 9, "Doug", "2913745445_81f10d0b3c_t.jpg", 88888, "Yellow"],
54 | [1, 10, "Doug", "3545922423_cffb4ecb04_t.jpg", 88888, "Yellow flower"],
55 | [1, 11, "Doug", "3122503680_6975c6faaf_t.jpg", 88888, "The blues and the greens"],
56 | [1, 12, "Doug", "3103809905_607649a798_t.jpg", 88888, "Sing the Blues"],
57 | [1, 13, "Doug", "4530628192_1427fd44d9_t.jpg", 88888, "Canon T2i Flower"],
58 | [1, 14, "Doug", "3757385629_b58653d59b_t.jpg", 88888, "Macro flower experiment"],
59 | [1, 15, "Doug", "4522243047_1815f626bd_t.jpg", 88888, "The Daisy"],
60 | [1, 16, "Doug", "3555700749_ddbb69293e_t.jpg", 88888, "Precious Gift"]
61 | ]
62 | }
63 | ```
64 |
65 | **Alternate Output**
66 |
67 | If we change the code to ourput as a struct.
68 | ```
69 |
70 |
71 |
72 |
73 | ```
74 |
75 | The output returns like so:
76 |
77 | ```
78 | {
79 | "iTotalDisplayRecords": 16,
80 | "iTotalRecords": 16,
81 | "aaData": [{
82 | "img_thumb": "8318007055_fa1c3dc930_t.jpg",
83 | "first_name": "Doug",
84 | "artwork_id": 1,
85 | "artist_id": 1,
86 | "last_name": 88888,
87 | "title": "Flower"
88 | }, {
89 | "img_thumb": "2808827891_223469fd22_t.jpg",
90 | "first_name": "Doug",
91 | "artwork_id": 2,
92 | "artist_id": 1,
93 | "last_name": 88888,
94 | "title": "Yellow flowers"
95 | },
96 |
97 | // etc.
98 |
99 | {
100 | "img_thumb": "3555700749_ddbb69293e_t.jpg",
101 | "first_name": "Doug",
102 | "artwork_id": 16,
103 | "artist_id": 1,
104 | "last_name": 88888,
105 | "title": "Precious Gift"
106 | }]
107 | }
108 | ```
109 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | cfquery-to-json
2 | ===============
3 |
4 | A collection of JSON converters for ColdFusion query objects.
5 |
--------------------------------------------------------------------------------
/docs/_config.yml:
--------------------------------------------------------------------------------
1 | theme: jekyll-theme-slate
--------------------------------------------------------------------------------
/docs/index.md:
--------------------------------------------------------------------------------
1 | # Testing
2 |
3 | A collection of tools to convert ColdFusion query objects to structs and arrays, then serialize those to varous forms of JSON.
4 |
--------------------------------------------------------------------------------