How to parse complex nested JSON data in NodeJS - javascript

I'm having kind of complex nested JSON in my dynamoDB, I want to extract this Filter object and its values. For example, if Type is macBook return the Filter object and its value PRO and AIR. Please find my code below and JSON input - I'm struggling to parse these value in NodeJS - could someone please help me - how to get the Filter Object?
JSON
{
"ProductType": {
"S": "Apple"
},
"Type": {
"M": {
"iPhone": {
"M": {
"Filter": {
"M": {
"model": {
"SS": [
"X", "XS"
]
}
}
}
}
},
"macBook": {
"M": {
"Filter": {
"M": {
"model": {
"SS": [
"PRO", "AIR"
]
}
}
}
}
}
}
}
}
product.js
const AWS = require('aws-sdk');
var dynamodb = new AWS.DynamoDB({
region: process.env.AWS_REGION,
});
const getModel = function (productType) {
return new Promise((resolve, reject) => {
var params = {
Key: {
"ProductType": {
S: productType
}
},
TableName: 'product'
};
dynamodb.getItem(params, function (err, data) {
if (err) reject(err, err.stack);
else {
console.log("data: " + Object.keys(data));
let product = data.Item.ProductType.S;
let filterModel = data.Item.Type.M
console.log(filterModel);
}
});
});
}
getModel('Apple')
Any help would be much appreciated

You need to use Object.values to get the values of iPhone and macbook objects, then inside you can use flatMap to find the Filter whose has PRO", "AIR" properties.
const data ={
"ProductType": {
"S": "Apple"
},
"Type": {
"M": {
"iPhone": {
"M": {
"Filter": {
"M": {
"model": {
"SS": [
"X", "XS"
]
}
}
}
}
},
"macBook": {
"M": {
"Filter": {
"M": {
"model": {
"SS": [
"PRO", "AIR"
]
}
}
}
}
}
}
}
}
const result = Object.values(data.Type.M).flatMap((item) => {
const SS = item.M.Filter.M.model.SS
return SS.includes('PRO') && SS.includes('AIR') ? [{ Filter: item.M.Filter.M }] : []
}, [])
console.log(result)

Related

How to filtering out the multiple nested object in Javascript object

Javascript
I have a nested array of objects, I'm trying to filter the given array of objects using a property from the third level of its array property value. For example, from the below array I like to filter the entire array using the property ListId: 10
Example
let test = {
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":11,
"name":"string2",
"state":"BY"
},
{
"ListId":12,
"name":"string3",
"state":"BY"
}
]
}
]
},
{
"name":"header2",
"value":[
{
"id":"01",
"list":[
{
"ListId":100,
"name":"string1",
"state":"BY",
"techId":0
},
{
"ListId":111,
"name":"string2",
"state":"BY"
},
{
"ListId":121,
"name":"string3",
"state":"BY"
}
]
}
]
}
]
}
Filtervalue with ListId = 10
Expected output :
{
"test":true,
"group":[
{
"name":"header",
"value":[
{
"id":"0",
"list":[
{
"ListId":10,
"name":"string1",
"state":"BY",
"techId":0
}
]
}
]
}
]
}
How can I use the filter method using javascript to get this expected result?
You can two it in two times :
First, filter the list arrays,
Secondly filter the groups array using the some method
let test= {
"test": true,
"group": [
{
"name": "header",
"value": [
{
"id": "0",
"list": [
{
"ListId": 10,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 11,
"name": "string2",
"state": "BY"
},
{
"ListId": 12,
"name": "string3",
"state": "BY"
}
]
}
]
},
{
"name": "header2",
"value": [
{
"id": "01",
"list": [
{
"ListId": 100,
"name": "string1",
"state": "BY",
"techId": 0
},
{
"ListId": 111,
"name": "string2",
"state": "BY"
},
{
"ListId": 121,
"name": "string3",
"state": "BY"
}
]
}
]
}
]
}
test.group.forEach(group => {
group.value.forEach(value => {
value.list = value.list.filter(list => list.ListId === 10)
})
})
test.group = test.group.filter(group => group.value.some(value => value.list.length > 0))
console.log(test)
Note : You should use plural names for you arrays, it helps understanding the data. For example lists not list for the array.
let z ={"group1": [
{
"name": "header",
"value": [
{
"id": 0,
"list": [
{
"ListId": 10,
"Name": "string1"
},
{
"ListId": 11,
"Name": "string2"
}
]
}
]
}
]}
// This function was written from understading that 'group1' is not a fixed property, but part of a dynamic list due to the number '1'
const getItemByListId = (list, listId) => {
const listKeys = Object.keys(list);
const selectedListKey = listKeys.find(key => {
const groupItems = list[key];
const selectedItem = groupItems.find(({ value: nestedItems }) => {
const selectedNestedItem = nestedItems.find(({ list }) => {
const selectedList = list.find(({ ListId }) => ListId === listId)
return selectedList;
});
return selectedNestedItem;
});
return selectedItem;
});
if (!selectedListKey) {
return null;
}
return list[selectedListKey];
};
console.log(getItemByListId(z, 10));

AngularJS: Object manipulation: flattening object in js

I have an object received in response from backend, and would like to extract elements of object and attach them to scope to make it available in the View.
Following is the structure of the object:
{
"Name": {
"S": "Jon Snow"
},
"Location": {
"S": "Winterfell"
},
"Details": {
"M": {
"Parents": {
"M": {
"mother": {
"S": "Lynna Stark"
}
}
},
"Dog": {
"N": "Ghost Snow"
}
}
}
}
Since I have received it from backend, I don't know what kind of object is this, and I want to convert it to a plain JSON object which should be looking something like this:
{
"Name": "Jon Snow",
"Location": "Winterfell",
"Details": {
"Parents": {
"mother": "Lynna Stark"
},
"Dog": "Ghost Snow"
}
}
Help is appreciated, as I am a beginner in AngularJS and also It would be good if someone elaborates what kind of Object did I receive? Thanks in advance.
Update 1:
Thanks for the responses. Now I have got the idea. Now the question is how to I flatten the object by one level? And If I do flatten does it tamper the original response as it is received from the backend, it may be different every time.
const data = {
"Name": {
"S": "Jon Snow"
},
"Location": {
"S": "Winterfell"
},
"Details": {
"M": {
"Parents": {
"M": {
"mother": {
"S": "Lynna Stark"
}
}
},
"Dog": {
"N": "Ghost Snow"
}
}
}
}
const flatten = (data) =>{
if(typeof data === "string") return data;
for(let key in data){
for(let deep in data[key]){
if(deep.length === 1){
const temp = data[key]
data[key] = flatten(temp[deep])
}
}
}
return data;
}
console.log( JSON.stringify(flatten(data), null, "\t"))
JS bin

Is there any way to replace the existing object inside JSON array with new object based on key

I am having a dynamic JSON array in below format,
let main_data = [
{
"client":[
{
"name":"aaaa",
"count":"1",
"filter":{
"type":{
"name":"test3"
}
}
},
{
"name":"bbbb",
"count":"9",
"filter":{
"type":{
"name":"test2"
}
}
}
]
},
{
"compute":[
{
"name":"cccc",
"count":"6",
"filter":{
"type":{
"name":"test"
}
}
}
]
}
]
Here key "name" is unique. When updating a form, I will get an json array like below,
let new_data = [
{
"client":[
{
"name":"bbbb",
"count":"1234",
"type":{
"name":"updated_name"
}
}
}
]
}
]
I need to check the "name" in the json array in "main_data" and remove the existing one and update with the new "updated_data" into the "main_data". (no Jquery please)
Expected output,
let main_data = [
{
"client":[
{
"name":"aaaa",
"count":"1",
"filter":{
"type":{
"name":"test3"
}
}
},
{
"name":"bbbb",
"count":"123",
"filter":{
"type":{
"name":"updated_name"
}
}
}
]
},
{
"compute":[
{
"name":"cccc",
"count":"6",
"filter":{
"type":{
"name":"test"
}
}
}
]
}
]
Is there any way to achive this. Any help would be much appreciated. Thanks in advance.
Try this
let main_data = [{
client: [{
name: "aaaa",
count: "1",
filter: {
type: {
name: "test3"
}
}
},
{
name: "bbbb",
count: "9",
filter: {
type: {
name: "test2"
}
}
}
]
},
{
compute: [{
name: "cccc",
count: "6",
filter: {
type: {
name: "test"
}
}
}]
}
];
let new_data = [{
client: [{
name: "bbbb",
count: "1234",
filter: {
type: {
name: "updated_name"
}
}
}]
}];
const res = main_data.map((item, index) => {
if (item.client) {
const clients = item.client.map(client => {
if (client.name === new_data[0].client[0].name) {
client = new_data[0].client[0];
}
return client;
});
return {
client: clients
};
}
return item;
});
console.log(res);
There may very well be a fancy way to get this done but one can always just find the matching item and replace it. eg.
let main_data = [
{
"client": [
{
"name": "aaaa",
"count": "1",
"filter": {
"type": {
"name": "test3"
}
}
},
{
"name": "bbbb",
"count": "123",
"filter": {
"type": {
"name": "updated_name"
}
}
}
]
},
{
"compute": [
{
"name": "cccc",
"count": "6",
"filter": {
"type": {
"name": "test"
}
}
}
]
}
];
let new_data = [
{
"client": [
{
"name": "bbbb",
"count": "1234",
"type": {
"name": "updated_name"
}
}
]
}
];
console.log("before:" + JSON.stringify(main_data));
newItem = new_data[0]["client"][0];
mainDataList = main_data[0]["client"];
for (i = 0; i < mainDataList.length; i++) {
if (mainDataList[i].name == newItem.name) {
mainDataList[i] = newItem;
}
}
console.log("after:" + JSON.stringify(main_data));
will output
before:[{"client":[{"name":"aaaa","count":"1","filter":{"type":{"name":"test3"}}},{"name":"bbbb","count":"123","filter":{"type":{"name":"updated_name"}}}]},{"compute":[{"name":"cccc","count":"6","filter":{"type":{"name":"test"}}}]}]
after:[{"client":[{"name":"aaaa","count":"1","filter":{"type":{"name":"test3"}}},{"name":"bbbb","count":"1234","type":{"name":"updated_name"}}]},{"compute":[{"name":"cccc","count":"6","filter":{"type":{"name":"test"}}}]}]
Here's a simple way to do this, let's say your new data is at variable newData:
main_data.client.filter(item => item.name === newData.name).push(newData)

Using batchWriteItem in dynamodb

I have two tables in my dynamo db one is candidate table and the other one is user table I want to use batchWriteItem in dynamo db in order to add the data in the table.
The query which I have formatted is as follows
var user = {
userid: usrid,
role: 'candidate',
password: vucrypt.encryptpass(pass)
};
var canduser = {
fname: req.body.fname,
lname: req.body.lname,
location: req.body.location,
phone: req.body.phone,
ccode: req.body.ccode,
grad: req.body.grad,
pgrad: req.body.pgrad,
ograd: req.body.ograd,
experience: exp,
linkedin: req.body.linkedin,
terms: tandc
};
canduser = vutools.fixcanduser(canduser);
canduser.userid = usrid;
var writes = {
'users': [{put: user}],
'candidate': [{put: canduser}],
};
But if i use
dynamodb.batchWriteItem(writes, function(err, regdata) {
}
Its ending up as error.
How can I write the right query? The error I am getting is this.
MultipleValidationErrors: There were 3 validation errors:
* MissingRequiredParameter: Missing required key 'RequestItems' in params
* UnexpectedParameter: Unexpected key 'users' found in params
* UnexpectedParameter: Unexpected key 'candidate' found in params
To batchwrite in DynamoDB, the data must be formated in the dynamodb way.
if you want do it in standard json, go for the documentclient.
you have an example below, have in mind that dynamobb batchwrite only accept mawimum of 25 element by request.
so according to the doc you must have :
1. Attributes
"ATTRIBUTE_1": { "S": "ATTRIBUTE_1_VALUE" }
According to your example :
"role": {"S":"candidate"}
2. Items
Each item must have this format
PutRequest: {
Item: {
...,
"ATTRIBUTE_1": { "S": "ATTRIBUTE_1_VALUE" },
...
}
}
3. Array of items to add
Create an array of items, which doesn't exceed 25 elements, (it's a dynamodb limit for batchwrite)
4. Your request params
put it together
var params = {
RequestItems: {
"TABLE_NAME": [
//the array you just created in step 3
]
}
}
5. The request
ddb.batchWriteItem(params, function(err, data) {
if (err) {
console.log("Error", err);
} else {
console.log("Success", data);
}
});
UPDATE
Your example will be something like this :
var params = {
"RequestItems": {
"TABLE_NAME": [
{
"PutRequest": {
Item: {
"userid": { "N": "usrid" },
"role": { "S": 'candidate' },
"password": { "S": vucrypt.encryptpass(pass) }
}
}
}
],
"TABLE_NAME2": [
{
"PutRequest": {
Item: {
"fname": {
"S": req.body.fname
},
"lname": {
"S": req.body.lname
},
"location": {
"S": req.body.location
},
"phone": {
"S": req.body.phone
},
"ccode": {
"S": req.body.ccode
},
"grad": {
"S": req.body.grad
},
"pgrad": {
"S": req.body.pgrad
},
"ograd": {
"S": req.body.ograd
},
"experience": {
"S": exp
},
"linkedin": {
"S": req.body.linkedin
},
"terms": {
"S": tandc
}
}
}
}
]
}
}
This is the right answer there are some type problems.
var createuser = {
"RequestItems": {
"users": [{
"PutRequest": {
Item: {
"userid": {
"S": usrid +""
},
"password": {
"S": vucrypt.encryptpass(pass) +""
},
"role": {
"S": 'candidate' +""
}
}
}
}],
"candidate": [{
"PutRequest": {
Item: {
"ccode": {
"S": req.body.ccode +""
},
"fname": {
"S": req.body.fname +""
},
"lname": {
"S": req.body.lname +""
},
"pgrad": {
"S": req.body.pgrad +""
},
"videoresumeurl": {
"S": "-"
},
"phone": {
"S": req.body.phone +""
},
"terms": {
"S": tandc +""
},
"location": {
"S": req.body.location +""
},
"experience": {
"N": req.body.experience +""
},
"userid": {
"S": usrid +""
},
"grad": {
"S": req.body.grad +""
}
}
}
}]
}
}

searching for repeated properties in objects in an associative array

I need to find out if one user appears more than once in the associative array (and then sum the value of the same tasks). How do I do that in javaScript?
{
"Items": [
{
"Date": {
"N": "1439883817221"
},
"UserName": {
"S": "user1"
},
"task1": {
"N": "9"
}
},
{
"Date": {
"N": "1439892361108"
},
"task2": {
"N": "3"
},
"UserName": {
"S": "user2"
}
},
{
"Date": {
"N": "1439904242126"
},
"UserName": {
"S": "user1"
},
"task2": {
"N": "2"
}
}
}}
Try this:
var uniqueNames = [];
var nonUniqueNames = [];
$.each( list.Items, function(i, item ) {
if(uniqueNames.indexOf(item.UserName.S) != -1 ){
nonUniqueNames.push(item.UserName.S);
} else {
uniqueNames.push(item.UserName.S);
}
});
alert(nonUniqueNames);
https://jsfiddle.net/c2co1hck/
As for the same tasks you can figure out the same way to do it.
Please define the same tasks anyway as you have different names and values for it.
Posting some of your code would also be appreciated.
By the way you have an error in your JSON, it should end with
]} not with }}

Categories