node.js merging two json documents using request - javascript

I'm having trouble getting two JSON APIs on a website to merge into a single array rather than two.
My two JSON strings look like this:
{
"users": [
{
"name": "test1",
"uniqueid": "randomlygeneratedUUID"
},
{
"name": "test2",
"uniqueid": "randomlygeneratedUUID"
},
{
"name": "test3",
"uniqueid": "randomlygeneratedUUID"
}
}
{
"users": [
{
"name": "test4",
"uniqueid": "randomlygeneratedUUID"
},
{
"name": "test5",
"uniqueid": "randomlygeneratedUUID"
},
{
"name": "test6",
"uniqueid": "randomlygeneratedUUID"
}
}
and using something like Request, I grab the two URLs (the code looks like this):
var RequestMultiple = function (urls, callback) {
'use strict';
var results = {}, t = urls.length, c = 0,
handler = function (error, response, body) {
var url = response.request.uri.href;
results[url] = { error: error, response: response, body: body };
if (++c === urls.length) { callback(results); }
};
while (t--) { request(urls[t], handler); }
};
var DoRequest = function() {
var urls = ["url1", "url2"];
RequestMultiple(urls, function(responses) {
for (url in responses) {
response = responses[url];
if (response.body){
var JsonBody1 = JSON.parse(response[urls[0]]);
var JsonBody2 = JSON.parse(response[urls[1]]);
var MergeJsonBody = JsonBody1.concat(JsonBody2);
console.log(JSON.stringify(MergeJsonBody).toString());
} else {
console.log('Url', url, response.error);
}
}
});
});
console.log(DoRequest());
The issue I'm having is it doesn't merge, but when it does it looks like this:
{"users": [{ "name": "test1","uniqueid": "randomlygeneratedUUID"},{ "name": "test2","uniqueid": "randomlygeneratedUUID"},{ "name": "test3","uniqueid": "randomlygeneratedUUID"}} unidentified {"users": [{ "name": "test4","uniqueid": "randomlygeneratedUUID"},{ "name": "test5","uniqueid": "randomlygeneratedUUID"},{ "name": "test6","uniqueid": "randomlygeneratedUUID"}}
And it returns an error about the string unidentified.
When I don't get that error, it only shows the second JSON body.
What am I doing wrong? And is there a module or a best in practice way to do this?
EDIT:
Okay I took the solution provided, and I still hit a wall. To counter the issues I basically just had two unique requests that add to a local array variable, then once the command was triggered, create the array, then erase all the items from the array and start all over again. Thanks for all the help!

First of all both of your JSONs are missing closing square brackets. I guess its typo but below is the correct JSON.
{
"users": [
{
"name": "test4",
"uniqueid": "randomlygeneratedUUID"
},
{
"name": "test5",
"uniqueid": "randomlygeneratedUUID"
},
{
"name": "test6",
"uniqueid": "randomlygeneratedUUID"
}
]
}
Now change below line of code
JsonBody1.concat(JsonBody2);
to
JsonBody1.users.concat(JsonBody2.users);
This will should give you expected results. You are doing concat on the actual objects instead of arrays.

Related

Reverse Traverse a hierarchy

I have a hierarchy of objects that contain the parent ID on them. I am adding the parentId to the child object as I parse the json object like this.
public static fromJson(json: any): Ancestry | Ancestry[] {
if (Array.isArray(json)) {
return json.map(Ancestry.fromJson) as Ancestry[];
}
const result = new Ancestry();
const { parents } = json;
parents.forEach(parent => {
parent.parentId = json.id;
});
json.parents = Parent.fromJson(parents);
Object.assign(result, json);
return result;
}
Any thoughts on how to pull out the ancestors if I have a grandchild.id?
The data is on mockaroo curl (Ancestries.json)
As an example, with the following json and a grandchild.id = 5, I would create and array with the follow IDs
['5', '0723', '133', '1']
[{
"id": "1",
"name": "Deer, spotted",
"parents": [
{
"id": "133",
"name": "Jaime Coldrick",
"children": [
{
"id": "0723",
"name": "Ardys Kurten",
"grandchildren": [
{
"id": "384",
"name": "Madelle Bauman"
},
{
"id": "0576",
"name": "Pincas Maas"
},
{
"id": "5",
"name": "Corrie Beacock"
}
]
},
There is perhaps very many ways to solve this, but in my opinion the easiest way is to simply do a search in the data structure and store the IDs in inverse order of when you find them. This way the output is what you are after.
You could also just reverse the ordering of a different approach.
I would like to note that the json-structure is a bit weird. I would have expected it to simply have nested children arrays, and not have them renamed parent, children, and grandchildren.
let data = [{
"id": "1",
"name": "Deer, spotted",
"parents": [
{
"id": "133",
"name": "Jaime Coldrick",
"children": [
{
"id": "0723",
"name": "Ardys Kurten",
"grandchildren": [
{
"id": "384",
"name": "Madelle Bauman"
},
{
"id": "0576",
"name": "Pincas Maas"
},
{
"id": "5",
"name": "Corrie Beacock"
}
]
}]
}]
}]
const expectedResults = ['5', '0723', '133', '1']
function traverseInverseResults(inputId, childArray) {
if(!childArray){ return }
for (const parent of childArray) {
if(parent.id === inputId){
return [parent.id]
} else {
let res = traverseInverseResults(inputId, parent.parents || parent.children || parent.grandchildren) // This part is a bit hacky, simply to accommodate the strange JSON structure.
if(res) {
res.push(parent.id)
return res
}
}
}
return
}
let result = traverseInverseResults('5', data)
console.log('results', result)
console.log('Got expected results?', expectedResults.length === result.length && expectedResults.every(function(value, index) { return value === result[index]}))

cannot update an array of elements via a 2d iteration

I have two arrays of object, the first array (printerChart, around 80 elements) is made of the following type of objects:
[{
printerBrand: 'Mutoh',
printerModel: 'VJ 1204G',
headsBrand: 'Epson',
headType: '',
compatibilty: [
'EDX',
'DT8',
'DT8-Pro',
'ECH',
],
},
....
]
The second array (items, around 500 elements) is made of the following type of objects:
[
{
"customData": {
"brand": {
"value": {
"type": "string",
"content": "hp"
},
"key": "brand"
},
"printer": {
"value": {
"type": "string",
"content": "c4280"
},
"key": "printer"
}
},
"name": "DT8 XLXL",
"image": {
"id": "zLaDHrgbarhFSnXAK",
"url": "https://xxxxxxx.net/images/xxxxxx.jpg"
},
"brandId": "xxxxx",
"companyId": "xxxx",
"createdAt": "2018-03-26T14:39:47.326Z",
"updatedAt": "2018-04-09T14:31:38.169Z",
"points": 60,
"id": "dq2Zezwm4nHr8FhEN"
},
...
]
What I want to do is to iterate via the second array and, if the part of the name of an item (i.e. DT8) is included in an element of the array 'compatibility' of the first array, I would like to include a new properties to it from the element of the first array: printerBrand. I have tried but somehow the iteration doesn't take place correctly. This is what I tried:
items.forEach((item) => {
printerChart.forEach((printer) => {
if (printer.compatibilty.some(compatibleElem => (
item.name.includes(compatibleElem)))) {
item.printerBrand = printer.printerBrand;
} else {
item.printerBrand = '';
}
});
});
What am I doing wrong?
You do
items.items.forEach(...)
Shouldn't you be doing
items.forEach(...)
?
I suggest to initialize item.printerBrand with an empty string and use a nested approach of some for getting a brand and to exit the loops, if found.
This prevents to get an empty string even if there is a brand to assign.
items.forEach((item) => {
item.printerBrand = '';
printerChart.some(printer => {
if (printer.compatibilty.some(compatibleElem => item.name.includes(compatibleElem))) {
item.printerBrand = printer.printerBrand;
return true;
}
});
});

How to iterate through deeply nested objects inside of a JSON?

I know there are plenty of questions about iterating through JSON objects but I haven't found one that quite relates to my exact problem. This is the JSON that I'm trying to iterate through:
psinsights = {
"kind": "pagespeedonline#result",
"id": "/speed/pagespeed",
"responseCode": 200,
"title": "PageSpeed Home",
"score": 90,
"pageStats": {
"numberResources": 22,
"numberHosts": 7,
"totalRequestBytes": "2761",
"numberStaticResources": 16,
"htmlResponseBytes": "91981",
"cssResponseBytes": "37728",
"imageResponseBytes": "13909",
"javascriptResponseBytes": "247214",
"otherResponseBytes": "8804",
"numberJsResources": 6,
"numberCssResources": 2
},
"formattedResults": {
"locale": "en_US",
"ruleResults": {
"AvoidBadRequests": {
"localizedRuleName": "Avoid bad requests",
"ruleImpact": 0.0
},
"MinifyJavaScript": {
"localizedRuleName": "Minify JavaScript",
"ruleImpact": 0.1417,
"urlBlocks": [
{
"header": {
"format": "Minifying the following JavaScript resources could reduce their size by $1 ($2% reduction).",
"args": [
{
"type": "BYTES",
"value": "1.3KiB"
},
{
"type": "INT_LITERAL",
"value": "0"
}
]
},
"urls": [
{
"result": {
"format": "Minifying $1 could save $2 ($3% reduction).",
"args": [
{
"type": "URL",
"value": "http://code.google.com/js/codesite_tail.pack.04102009.js"
},
{
"type": "BYTES",
"value": "717B"
},
{
"type": "INT_LITERAL",
"value": "1"
}
]
}
},
{
"result": {
"format": "Minifying $1 could save $2 ($3% reduction).",
"args": [
{
"type": "URL",
"value": "http://www.gmodules.com/ig/proxy?url\u003dhttp%3A%2F%2Fjqueryjs.googlecode.com%2Ffiles%2Fjquery-1.2.6.min.js"
},
{
"type": "BYTES",
"value": "258B"
},
{
"type": "INT_LITERAL",
"value": "0"
}
]
}
}
]
}
]
},
"SpriteImages": {
"localizedRuleName": "Combine images into CSS sprites",
"ruleImpact": 0.0
}
}
},
"version": {
"major": 1,
"minor": 11
}
};
Now, I'm trying to write a function that iterates through all of the ruleResults objects and returns an array of the localizedRuleName properties. According to the JSON, ruleResults has three member objects (AvoidBadRequests, MinifyJavaScript, and SpriteImages). Each of these has a localizedRuleName property I'm trying to access, but when I print out my array, it's blank. Here's how I've written my function:
function ruleList(results) {
var ruleArray = [];
for(var ruleName in results.formattedResults.ruleResults){
ruleArray[counter] = results.formattedResults.ruleResults[ruleName].localizedRuleName;
}
return ruleArray;
}
console.log(ruleList(psinsights));
Can you guys help me get on the right track? I used basically this same method to iterate through the pageStats of the JSON and it worked perfectly. I'm not sure why I can't get it to work with these deeper nested objects and properties.
your problem is not your iteration, but your undefined variable "counter".
Instead of using a counter can use the "push" function:
function ruleList(results) {
var ruleArray = [];
for(var ruleName in results.formattedResults.ruleResults){
ruleArray.push(results.formattedResults.ruleResults[ruleName].localizedRuleName);
}
return ruleArray;
}
fiddle: https://jsfiddle.net/fo9h56gh/
Hope this helps.
you're probably getting a javascript error since counter is not defined. you can try this:
function ruleList(results) {
var ruleArray = [];
var counter = 0;
for(var ruleName in results.formattedResults.ruleResults){
ruleArray[counter] = results.formattedResults.ruleResults[ruleName].localizedRuleName;
counter++;
}
return ruleArray;
}

angularjs: Push is not a function

I have a JSON object like this:
var post = {
"post_id": "1",
"content": "content",
"post_author": {
"id": "12",
"firstName": "Amelia",
"lastName": "Earheart",
},
"isLiked": false,
"likes_count": 0,
"likers": [],
"comments_count": 0,
"commenters": [],
"comments": []
};
And post is passed to the function given below from the front end.
var vm = this;
vm.likePost = function(post) {
var likedPost = post;
vm.userInfo();
likedPost.likers.push(userObject); //Here
myService.postLike(likedPost).success(function(data) {
likedPost.isLiked = true;
likedPost.likes_count++;
vm.posts = data;
});
};
But doing so, I get a JavaScript error saying push is not a function in line likedPost.likers.push(userObject);
And userObject is returned by vm.userInfo() and it looks like this:
vm.userInfo = function() {
myService.getBasicUserInfo().success(function(data) {
vm.currentPost.post_author.id = data.id;
vm.currentPost.post_author.firstName = data.firstName;
vm.currentPost.post_author.lastName = data.lastName;
});
};
and the returned JSON is like this:
{"id":"12","firstName":"Amelia","lastName":"Earheart"}
Can anyone help me figure out the cause of this issue?
UPDATE:
{
"post_id": "12",
"content": "Content is the content that contains the content",
"image": "member-default.jpg",
"created_at": "2016-05-26 14:29:00",
"post_author": {
"id": "12",
"firstName": "Amelia",
"lastName": "Earheart",
},
"isLiked": false,
}
This is what I get upon console.log(likedPost);
The output clearly specifies that likers is not defined. You can put a validation check before using push() method.
//if likedPost.likers is not defined, it will define it as an array
likedPost.likers = likedPost.likers || [];
//Do the push operation
likedPost.likers.push(userObject);
Your likedPost object doesn't have the likers array you expect. Probably you can see if that exists before trying to push.
if (typeof likedPost !== 'undefined')
likedPost.likers.push(userObject);

Knockout combining multiple json data into single vm

I want to combine multiple json data into a single vm. I read that you can map from js into the model multiple times and it should be merging but on my case, it's not. It's replacing the data.
function Item(ID, Name, Description) {
this.ID = ko.observable(ID);
this.Name = ko.observable(Name);
this.Description = ko.observable(Description);
}
var MasterViewModel = {
model: ko.observableArray([])
};
$.getJSON(url, function (response) {
ko.mapping.fromJS(response["TM1.Cube"], Item, MasterViewModel.model);
ko.mapping.fromJS(response["TM1.Dimension"], Item, MasterViewModel.model);
})
ko.applyBindings(MasterViewModel);
And here is my json data
{
"LogicalName": "TM1.Model",
"ID": "12345",
"Name: "Sample",
"TM1.Cube": [
{
"LogicalName": "TM1.Cube",
"ID": "111111",
"Name": Assets"
},
{
"LogicalName": "TM1.Cube",
"ID": "111112",
"Name": Finance"
}
],
"TM1.Dimension": [
{
"LogicalName": "TM1.Dimension",
"ID": "222221",
"Name": Assets"
},
{
"LogicalName": "TM1.Dimension",
"ID": "222222",
"Name": Finance"
}
]
}
and the outcome I expected is like this
{
"LogicalName": "TM1.Cube",
"ID": "111111",
"Name": Assets"
},
{
"LogicalName": "TM1.Cube",
"ID": "111112",
"Name": Finance"
},
{
"LogicalName": "TM1.Dimension",
"ID": "222221",
"Name": KPI"
},
{
"LogicalName": "TM1.Dimension",
"ID": "222222",
"Name": Default"
}
I have added a jsFiddle http://jsfiddle.net/e1ppj3qc/1/
The mapping plugin can take an existing model but I don't believe it will merge data.
For example you could map twice like so:
{one: "yo"}
and
{two: "dawg"}
into the same model and you would now have two observables, one() and two()
But if you was to do this (which you are):
{one: ["yo"]}
and
{one: ["dawg"]}
it will always overwrite the matched properties.
You could instead do the mapping and then simply push into the array that you want to add to like so:
function pushCubs(dataToPush) {
ko.utils.arrayPushAll(MasterViewModel.modelcub, dataToPush());
}
pushCubs(ko.mapping.fromJS(data));
pushCubs(ko.mapping.fromJS(data2));
http://jsfiddle.net/e1ppj3qc/2/

Categories

Resources