How can I apply pagination to a subobject in json-server? - javascript

I have a json-server with the following files:
db.json:
var faker = require('faker');
module.exports = function () {
var data = {
slack_users_list: slack_users_list(),
slack_users_info: slack_users_info()
}
return data;
}
function slack_users_list() {
const data = {
members: []
}
for (var i = 0; i < 10; i++) {
data.members.push({
id: "user_id_" + i
})
}
return data;
}
function slack_users_info() {
const data = {
user: []
}
for (var i = 0; i < 10; i++) {
data.user.push({
id: "user_id_" + i,
name: faker.internet.userName(),
team_id: faker.datatype.string(),
profile: {
title: faker.name.title(),
first_name: faker.name.firstName(),
last_name: faker.name.lastName(),
title: faker.name.title(),
email: faker.internet.email(),
phone: faker.phone.phoneNumber(),
skype: faker.internet.userName(),
},
})
}
return data;
}
And server.js:
const jsonServer = require('json-server')
const server = jsonServer.create()
const router = jsonServer.router(require('./db.js')())
const middlewares = jsonServer.defaults()
server.use(middlewares)
server.use(jsonServer.bodyParser)
// Wrap response depending on the object being called.
router.render = (req, res) => {
if (req.url.startsWith('/slack_users_list')) {
res.jsonp(res.locals.data)
} else if (req.url.startsWith('/slack_users_info')) {
param_user = req.query.user
if (param_user == null) {
res.jsonp({
"ok": false,
"error": "user_not_found"
})
return
}
user_list = res.locals.data.user
user_info = {}
for (var i = 0; i < user_list.length; i++) {
if (user_list[i].id == param_user) {
user_info = user_list[i]
}
}
res.jsonp({ user: user_info })
} else {
res.jsonp(res.locals.data)
}
}
server.use(router)
// Run server on indicated port.
server.listen(port = 3000, () => {
console.log('JSON Server is running')
console.log('http://localhost:' + port)
})
So when I call http://localhost:3000/slack_users_list I get:
{
"members": [
{
"id": "user_id_0"
},
{
"id": "user_id_1"
},
{
"id": "user_id_2"
},
{
"id": "user_id_3"
},
{
"id": "user_id_4"
},
{
"id": "user_id_5"
},
{
"id": "user_id_6"
},
{
"id": "user_id_7"
},
{
"id": "user_id_8"
},
{
"id": "user_id_9"
}
]
}
But if I want to apply pagination to it (e.g. http://localhost:3000/slack_users_list?_page=1&_limit=2), I get all the same objects, I assume because the pagination is getting applied to the first line of objects and not to each of the element inside members that get generated in db.json.
How can I modify this to apply the pagination on the sub-object members?
Thanks!

You can do the pagination right before sending the response.
// !!!
// This is just for demonstration.
// consider this req as the actual request.(req, res)
const req = {
params: { _page: '2', _limit:'3'}
}
// consider this as actual slack_users_list.members
const members = [
{
"id": "user_id_0"
},
{
"id": "user_id_1"
},
{
"id": "user_id_2"
},
{
"id": "user_id_3"
},
{
"id": "user_id_4"
},
{
"id": "user_id_5"
},
{
"id": "user_id_6"
},
{
"id": "user_id_7"
},
{
"id": "user_id_8"
},
{
"id": "user_id_9"
}
]
const page=Number(req.params._page)
const limit=Number(req.params._limit)
// paginating
const limited = members.slice((page - 1) * limit, page * limit)
console.log(limited)
// // send paginated response
//res.json(limited)

Related

Restructure Nested JSON Data And Removing Some Keys

I need to restructure a nested JSON data.
Here is how it looks like:
{
"MainKey1": [
{
"Section1": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Mapped Label": {
"Tag1": "1234567890"
}
}
}
}
},
{
"Section2": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Label": {
"Tag1": "111222333444"
},
"Tag2 Label": {
"Tag2": "121212"
},
"Tag3 Label": {
"Tag3": "0987654321"
}
}
}
}
}
],
"MainKey2": [
{
"Section1": {
"ParentTag1 Mapped Label": {
"ParentTag1": {
"Tag1 Mapped Label": {
"Tag1": "1234567890"
}
}
}
}
}
]
}
And this is a sample of the converted JSON:
{
MainKey: [
{
Section1: [
{
ParentTag1: [
{ Tag1: "1234567890" }
]
}
]
},
{
Section2: [
{
ParentTag1: [
{ Tag1: "111222333444" },
{ Tag2: "121212" },
{ Tag3: "0987654321" }
]
}
]
}
],
MainKey2: [
{
Section1: [
{
ParentTag1 : [
{ Tag1: "1234567890" }
]
}
]
}
]
}
Rules:
Everything inside a MainKey (outermost keys, could be any name) should be an array
All labels should be stripped (as the label could be any name, without the actual word "Label", we can determine if it is a label based on the depth level. Since the JSON will have the label as the parent and the actual "tag" as a child.
Here is what I currently have (it is a mess, sorry!)
function convertJson (jsonObj) {
const mainKeys = Object.keys(jsonObj)
let output = {}
for (let i = 0; i < mainKeys.length; i++) {
const mainKey = mainKeys[i]
let result = []
output[mainKey] = result
for (let j = 0; j < jsonObj[mainKey].length; j++) {
const innerObj = {...jsonObj[mainKey][j]}
const sectionName = Object.keys(innerObj)[0]
const sectionObj = {}
sectionObj[sectionName] = []
const index = result.push(sectionObj) - 1
parseObj(innerObj[sectionName], result[index], 0) // if I change 2nd param to: result, it generates incorrect output
}
}
console.log(output)
}
function parseObj (innerObj, result, depthCount) {
for (var key in innerObj) {
if (typeof innerObj[key] === "object") {
if (depthCount % 2 === 1) {
const parentObj = {}
parentObj[key] = []
result.push(parentObj)
depthCount++
parseObj(innerObj[key], parentObj[key], depthCount)
} else {
depthCount++
parseObj(innerObj[key], result, depthCount)
}
} else {
const keyValuePairObj = {}
keyValuePairObj[key] = innerObj[key]
result.push(keyValuePairObj)
}
}
return result
}
convertJson(json)
But it generates an error:
Uncaught TypeError: result.push is not a function
Now if I change line 90 from:
parseObj(innerObj[sectionName], result[index], 0)
to:
parseObj(innerObj[sectionName], result, 0)
Here is incorrect output:
{
"MainKey1": [
{
"Section1": []
},
{
"ParentTag1": [
{
"Tag1": "1234567890"
}
]
},
{
"Section2": []
},
{
"ParentTag1": [
{
"Tag1": "111222333444"
},
{
"Tag2 Label": [
{
"Tag2": "121212"
}
]
},
{
"Tag3": "0987654321"
}
]
}
],
"MainKey2": [
{
"Section1": []
},
{
"Tag1": "1234567890"
}
]
}
And here is my fiddle:
https://jsfiddle.net/kzaiwo/L4avxmyd/36/
Thanks a lot! Appreciate any help!

Real json value is more different then expected value using javascript / node js

I am destructing the data from the function
let { destructValue } = require("./destructValue.js");
const fs = require("fs");
const path = require("path");
function retrunValues(data) {
fs.readdir("./userData", (err, files) => {
if (err) throw console.log(err.message);
else {
files.forEach(async (file) => {
fs.readFile(`./userData/${file}`, (err, data) => {
destructValue(data);
let jsonObject = {};
if (destructValue(data).length !== 0) {
jsonObject = {
name: data.name,
value: [...destructValue(data)],
};
console.log(jsonObject);
}
});
});
}
});
}
so after doing console.log(jsonObject) I am getting this values
{
name: "Tomas",
value:[{
age: "21",
address: "New York"
}]
}
{
name: "Jerry",
value:[{
age: "22",
address: "Tokyo"
}]
}
this output look fine to me as this was the expected output so I tried to call jsonObject into new schema like this
let { destructValue } = require("./destructValue.js");
const fs = require("fs");
const path = require("path");
function retrunValues(data) {
fs.readdir("./userData", (err, files) => {
if (err) throw console.log(err.message);
else {
files.forEach(async (file) => {
fs.readFile(`./userData/${file}`, (err, data) => {
destructValue(data);
let jsonObject = {},
testingObject = {};
if (destructValue(data).length !== 0) {
jsonObject = {
name: data.name,
value: [...destructValue(data)],
};
}
testingObject = {
default: "default value",
got: jsonObject,
};
console.log(testingObject);
});
});
}
});
}
so after doing console.log(testingObject) I am getting this value
{ default: 'defaultObject'}
{ default: 'defaultObject'}
{ default: 'defaultObject',
name: "Tomas",
value:[{
age: "21",
address: "New York"
}]
}
{ default: 'defaultObject'}
{ default: 'defaultObject'}
{ default: 'defaultObject',
name: "Jerry",
value:[{
age: "22",
address: "Tokyo"
}]
}
As I was not expecting this output as my expected output was like this
[
{
"default": "defaultObject",
"got": [
{
"name": "Tomas",
"value": [{ "age": "21", "address": "New York" }]
},
{
"name": "Jerry",
"value": [{ "age": "22", "address": "Tokyo" }]
}
]
}
]
but I am not getting the expected value and I don't know where it went wrong how can I achieve my expected value
destructValue.js
const {age,address}=require(valueGot.js);
function destructValue(data){
const destructSchema=[];
for(const value of data){
switch(value.userDetails){
case "age":
destructSchema.push(age(data));
break;
case "address":
destructSchema.push(address(data));
break;
}
}
return destructSchema;
}
module.exports={destructValue}
Try the below. Save your results into an array and when you have finished going through the files, you output your results.
Edit: I added a filter for the results, but haven't tested. It should only add destructed data that hasn't been added before.
let { destructValue } = require("./destructValue.js");
const fs = require("fs");
const path = require("path");
function filterAgainstExisting(existing, check) {
return check.reduce((carry, value, index, array) => {
//Check if value exists - not generic, catered to your needs
if (existing[value.name] && existing[value.name].age == value.value[0].age && existing[value.name].address == value.value[0].address) {
return carry;
}
existing[value.name] = value;
carry.push(value);
return carry;
}, []);
}
function retrunValues(data) {
fs.readdir("./userData", (err, files) => {
if (err) throw console.log(err.message);
else {
let jsonArray = [];
let jsonObject = {};
files.forEach(async (file) => {
fs.readFile(`./userData/${file}`, (err, data) => {
let destructedData = destructValue(data);
if (destructedData.length !== 0) {
jsonArray.push({
name: data.name,
value: [...this.filterAgainstExisting(jsonObject, destructedData)],
});
}
});
});
const testingObject = [{
default: "defaultObject",
got: jsonArray,
}];
console.log(testingObject);
}
});
}
Try changing requrie
let {destructValue} = requrie("./destructeValue.js");
to require
let {destructValue} = require("./destructeValue.js");

Firestore bulk add field to array

I am struggling to add a field to an map in an array. I am trying to add "canAssist": false to each map in the array for each of the countries.
Here is my database:
[
{
"Afghanistan": {
"country": "Afghanistan",
"countryCode": "AF",
"countryCodeAlt": "AFG",
"emoji": "🇦🇫",
"packages": [
{
"name": "Luxury Couple",
"cost": "$2000.00",
// I want to add canAssist:false here!
},
{
"name": "Quick Retreat",
"cost": "$1000.00",
// I want to add canAssist:false here!
}
]
}
},
{...}
{...}
]
This is what I've tried:
let travelData = database.collection('countries').doc(docName);
travelData.get()
.then(function(querySnapshot) {
querySnapshot.forEach(function(array) {
packages.map(package => {
return package.add({
canAssist: false
});
})
});
});
You can use Object.values() and object destructuring to achieve this.
const querySnapshot = [
{
Afghanistan: {
country: 'Afghanistan',
countryCode: 'AF',
countryCodeAlt: 'AFG',
emoji: '🇦🇫',
packages: [
{
name: 'Luxury Couple',
cost: '$2000.00',
// I want to add canAssist:false here!
},
{
name: 'Quick Retreat',
cost: '$1000.00',
// I want to add canAssist:false here!
},
],
},
},
{
...
},
{
...
},
];
const updateSnapshot = (snapshot, newData) => {
return snapshot.map(countryData => {
// only one field with the name of the country
const country = Object.values(countryData)[0];
let updatedCountry = { ...country };
const field = country[newData.field];
if (field) {
if (typeof field === 'string') {
updatedCountry[newData.field] = newData.values;
} else if (Array.isArray(field)) {
updatedCountry[newData.field] = field.map(data => ({ ...data, ...newData.values }));
}
}
return { [updatedCountry.country]: updatedCountry };
});
};
(() => {
console.log('Original', JSON.stringify(querySnapshot, null, 4));
const updatedSnapshot = updateSnapshot(querySnapshot, { field: 'packages', values: { canAssist: false } });
console.log('Updated', JSON.stringify(updatedSnapshot, null, 4));
const updatedSnapshot2 = updateSnapshot(querySnapshot, { field: 'emoji', values: '🇪🇸' });
console.log('Spanish!', JSON.stringify(updatedSnapshot2, null, 4));
})();
Of course, you don't need to have that dynamism with the 'newData', I just added in case you want to play around any field of your datasource.

Pushing array but i needed no quotes

i have problem when im using array into my render apps..
here my code for getting list chat from sqlite..
return new Promise(resolve => {
const listchat = [];
this.initDB()
.then(db => {
db.transaction(tx => {
tx.executeSql(
'SELECT num, text, type, _id,user FROM chat where CAST(user as INT) order by num desc',
[],
).then(([tx, results]) => {
var len = results.rows.length;
for (let i = 0; i < len; i++) {
let row = results.rows.item(i);
var user = {id: 2, avatar: null};
const {num, text, type, _id} = row;
listchat.push({
num,
text,
type,
_id,
user,
});
}
resolve(listchat);
});
})
.then(result => {
this.closeDatabase(db);
})
.catch(err => {
console.log(err);
});
})
});
and i got results from query like this :
[
{
"_id": "6d357f55-5fb8-4fec-ac5f-26cc1df4b98d",
"num": 1,
"text": "here must number 111111111111111111",
"type": null,
"user": {
"avatar": null,
"_id": 2
}
}
]
and what i need is no quotes on "avatar and id"
[
{
"_id": "6d357f55-5fb8-4fec-ac5f-26cc1df4b98d",
"num": 1,
"text": "here must number 111111111111111111",
"type": null,
"user": {
avatar: null,
_id: 2
}
}
]
the problem is on quotes.. someone have solution for this ?

how to map this array if i want to the Names of the groups listed in different "quesytion"

How can I get the names of different activity in an array by using map function in this type of response. So that in a new array, assume that activity[] i will get names of all the activities mention below.
if the array is
const response = [
{
"Groups" : {
"Roles" : {
"submission": {
"subject" : {
"name": "history",
}
}
}
}
}
];
I managed to do this using an IIFE but there may be cleaner ways
assuming there in one object in the array and no other path to other permission
const response = [
{
"Roles" : {
"Permission" : {
"PERMISSION1": {
"Activity" : {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity" : {
"name": "Manage Users",
}
}
}
}
}
];
let activities = (() => {
let res = []
for (let perm in response[0].Roles.Permission) {
for (let act in response[0].Roles.Permission[perm]) {
res.push(response[0].Roles.Permission[perm][act].name)
}
}
return res})()
console.log(activities)
At first, you should convert Permission object to array, cause object doesn't have method map.
Then you could use map function where you can collect all your permissions' names for every item in response
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
response.forEach((item) => {
item.Activities = Object.values(item.Roles.Permission).map((permission) => permission.Activity.name)
});
alert(JSON.stringify(response));
The only array you have is response. If each item in response has a Roles that has a Permission that has several keys with objects that have Activity with name then you can do the following:
var response = [
{
Roles: {
Permission: {
PERMISSION1: {
Activity: {
name: 'Manage Clients',
},
},
PERMISSION2: {
Activity: {
name: 'Manage Users',
},
},
},
},
},
];
console.log(
response.map(
(item) =>
Object.values(item.Roles.Permission)
.map(
(permission) => permission.Activity.name
)
)
);
I recommend using a flatMap, so use .reduce.
const response = [{
"Roles": {
"Permission": {
"PERMISSION1": {
"Activity": {
"name": "Manage Clients",
}
},
"PERMISSION2": {
"Activity": {
"name": "Manage Users",
}
}
}
}
}];
const activityNames = response.reduce(function (acc, res) {
const permissions = res.Roles.Permission;
const permissionKeys = Object.keys(permissions);
const names = permissionKeys.map(function(permissionKey) {
return permissions[permissionKey].Activity.name;
});
acc.push(...names);
return acc;
}, [])
console.log(activityNames); // ["Manage Clients", "Manage Users"]

Categories