Skip to content

Commit 3efb06d

Browse files
ckebossdanivek
authored andcommitted
Add excludeData flag to serialize and serializeAsync (#92)
closes #92 #91
1 parent f462504 commit 3efb06d

File tree

3 files changed

+94
-32
lines changed

3 files changed

+94
-32
lines changed

README.md

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,23 @@ The output data will be :
326326
}
327327
```
328328

329+
There is an available argument `excludeData` that will exclude the `data`
330+
property from the serialized object. This can be used in cases where you may
331+
want to only include the `topLevelMeta` in your response, such as a `DELETE`
332+
response with only a `meta` property, or other cases defined in the
333+
JSON:API spec.
334+
335+
```javascript
336+
// Synchronously (blocking)
337+
const result = Serializer.serialize('article', data, 'default', {count: 2}, true);
338+
339+
// Asynchronously (non-blocking)
340+
Serializer.serializeAsync('article', data, 'default', {count: 2}, true)
341+
.then((result) => {
342+
...
343+
});
344+
```
345+
329346
Some others examples are available in [tests folders](https://github.com/danivek/json-api-serializer/blob/master/test/)
330347

331348
### Deserialize

lib/JSONAPISerializer.js

Lines changed: 39 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -73,9 +73,10 @@ module.exports = class JSONAPISerializer {
7373
* @param {object|object[]} data input data.
7474
* @param {string|object} [schema='default'] resource's schema name.
7575
* @param {object} [extraData] additional data that can be used in topLevelMeta options.
76+
* @param {boolean} [excludeData] boolean that can be set to exclude the `data` property in serialized data.
7677
* @returns {object} serialized data.
7778
*/
78-
serialize(type, data, schema, extraData) {
79+
serialize(type, data, schema, extraData, excludeData) {
7980
// Support optional arguments (schema)
8081
if (arguments.length === 3) {
8182
if (typeof schema === 'object') {
@@ -107,13 +108,21 @@ module.exports = class JSONAPISerializer {
107108
options = this.schemas[type][schema];
108109
}
109110

111+
let dataProperty;
112+
113+
if (excludeData) {
114+
dataProperty = undefined;
115+
} else if (isDynamicType) {
116+
dataProperty = this.serializeMixedResource(options, data, included, extraData);
117+
} else {
118+
dataProperty = this.serializeResource(type, data, options, included, extraData);
119+
}
120+
110121
return {
111122
jsonapi: options.jsonapiObject ? { version: '1.0' } : undefined,
112123
meta: this.processOptionsValues(data, extraData, options.topLevelMeta, 'extraData'),
113124
links: this.processOptionsValues(data, extraData, options.topLevelLinks, 'extraData'),
114-
data: isDynamicType
115-
? this.serializeMixedResource(options, data, included, extraData)
116-
: this.serializeResource(type, data, options, included, extraData),
125+
data: dataProperty,
117126
included: included.size ? [...included.values()] : undefined
118127
};
119128
}
@@ -128,9 +137,10 @@ module.exports = class JSONAPISerializer {
128137
* @param {object|object[]} data input data.
129138
* @param {string} [schema='default'] resource's schema name.
130139
* @param {object} [extraData] additional data that can be used in topLevelMeta options.
140+
* @param {boolean} [excludeData] boolean that can be set to exclude the `data` property in serialized data.
131141
* @returns {Promise} resolves with serialized data.
132142
*/
133-
serializeAsync(type, data, schema, extraData) {
143+
serializeAsync(type, data, schema, extraData, excludeData) {
134144
// Support optional arguments (schema)
135145
if (arguments.length === 3) {
136146
if (typeof schema === 'object') {
@@ -173,6 +183,9 @@ module.exports = class JSONAPISerializer {
173183
*/
174184
function next() {
175185
setImmediate(() => {
186+
if (excludeData) {
187+
return resolve();
188+
}
176189
if (i >= arrayData.length) {
177190
return resolve(serializedData);
178191
}
@@ -197,15 +210,27 @@ module.exports = class JSONAPISerializer {
197210
}
198211

199212
next();
200-
}).then(result => ({
201-
jsonapi: options.jsonapiObject ? { version: '1.0' } : undefined,
202-
meta: this.processOptionsValues(data, extraData, options.topLevelMeta, 'extraData'),
203-
links: this.processOptionsValues(data, extraData, options.topLevelLinks, 'extraData'),
204-
// If the source data was an array, we just pass the serialized data array.
205-
// Otherwise we try to take the first (and only) item of it or pass null.
206-
data: isDataArray ? result : result[0] || null,
207-
included: included.size ? [...included.values()] : undefined
208-
}));
213+
}).then(result => {
214+
let dataProperty;
215+
216+
if (typeof result === 'undefined') {
217+
dataProperty = undefined;
218+
} else if (isDataArray) {
219+
dataProperty = result;
220+
} else {
221+
dataProperty = result[0] || null;
222+
}
223+
224+
return {
225+
jsonapi: options.jsonapiObject ? { version: '1.0' } : undefined,
226+
meta: this.processOptionsValues(data, extraData, options.topLevelMeta, 'extraData'),
227+
links: this.processOptionsValues(data, extraData, options.topLevelLinks, 'extraData'),
228+
// If the source data was an array, we just pass the serialized data array.
229+
// Otherwise we try to take the first (and only) item of it or pass null.
230+
data: dataProperty,
231+
included: included.size ? [...included.values()] : undefined
232+
};
233+
});
209234
}
210235

211236
/**

test/unit/JSONAPISerializer.test.js

Lines changed: 38 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -858,12 +858,31 @@ describe('JSONAPISerializer', function() {
858858

859859
describe('serialize', function() {
860860
const Serializer = new JSONAPISerializer();
861+
const dataArray = [{
862+
id: 1,
863+
title: 'Article 1',
864+
}, {
865+
id: 2,
866+
title: 'Article 2',
867+
}, {
868+
id: 3,
869+
title: 'Article 3',
870+
}]
871+
861872
Serializer.register('articles', {
862-
topLevelMeta: {
863-
count: function(options) {
864-
return options.count
865-
}
866-
}
873+
topLevelMeta: (data, extraData) => ({
874+
count: extraData.count,
875+
total: data.length
876+
})
877+
});
878+
879+
it('should not include data property if excludeData is true', (done) => {
880+
const serializedData = Serializer.serialize('articles', dataArray, 'default', {count: 2}, true);
881+
expect(serializedData.data).to.be.undefined;
882+
expect(serializedData.meta).to.have.property('count', 2)
883+
expect(serializedData.meta).to.have.property('total', 3)
884+
expect(serializedData.included).to.be.undefined;
885+
done();
867886
});
868887

869888
it('should serialize empty single data', function(done) {
@@ -1003,30 +1022,31 @@ describe('JSONAPISerializer', function() {
10031022
}]
10041023

10051024
Serializer.register('articles', {
1006-
topLevelMeta: {
1007-
count: function(options) {
1008-
return options.count
1009-
}
1010-
}
1025+
topLevelMeta: (data, extraData) => ({
1026+
count: extraData.count,
1027+
total: data.length,
1028+
})
10111029
});
10121030

10131031
it('should return a Promise', () => {
10141032
const promise = Serializer.serializeAsync('articles', {});
10151033
expect(promise).to.be.instanceOf(Promise);
10161034
});
10171035

1018-
it('should serialize empty single data', () =>
1019-
Serializer.serializeAsync('articles', {})
1036+
it('should not include data property if excludeData is true', () => {
1037+
return Serializer.serializeAsync('articles', dataArray, 'default', {count: 2}, true)
10201038
.then((serializedData) => {
1021-
expect(serializedData.data).to.eql(null);
1039+
expect(serializedData.data).to.be.undefined;
1040+
expect(serializedData.meta).to.have.property('count', 2)
1041+
expect(serializedData.meta).to.have.property('total', 3)
10221042
expect(serializedData.included).to.be.undefined;
1023-
})
1024-
);
1043+
});
1044+
});
10251045

1026-
it('should serialize empty array data', () =>
1027-
Serializer.serializeAsync('articles', [])
1046+
it('should serialize empty single data', () =>
1047+
Serializer.serializeAsync('articles', {})
10281048
.then((serializedData) => {
1029-
expect(serializedData.data).to.eql([]);
1049+
expect(serializedData.data).to.eql(null);
10301050
expect(serializedData.included).to.be.undefined;
10311051
})
10321052
);

0 commit comments

Comments
 (0)