Javascript object nested filtering - javascript

I have an object parsed from JSON output.
I have to use only pure JS without any 3rd part libs. Can somebody suggest a working solution to filter a specific nested object by one of its key's value. In this sample I have a few "Fields" objects which contains also nested objects.
So is there a way to filter the whole nested object inside Fields using VName value as a filter criteria? For example use "VName": "oc_data" to filter the whole object inside Fields oc_data belongs to
[{
"Id": "0050560107dd",
"Name": "Demo Range",
"AllMup": false,
"Lines": [{
"Id": "0050560107dd",
"AllMup": false,
"Fields": [{
"Id": "0050560107dd",
"Name": "Some value here",
"VName": "oc_data",
"IsRequired": false,
"Format": {
"Type": "Dictionary",
"Dictionary": {
"Name": "Main stuff",
"SysName": "da3a45de77d1",
"ValuesUrl": "https://mysityurl.com",
"Id": "0050560107dd",
},
"CalForm": []
}
}]
},
{
"Id": "0050560107dd",
"AllMup": false,
"Fields": [{
"Id": "0050560107dd",
"Name": "Some value again",
"VName": "task_stat",
"IsRequired": false,
"Format": {
"Type": "Dictionary",
"Dictionary": {
"Name": "Task stuff",
"SysName": "Tasks.TaskState",
"ValuesUrl": "https://mysecondurl.com",
"Id": "ac1f6b17f99d",
},
"CalForm": []
}
}]
}
]
},
{
"Id": "0050560107dd",
"Name": "Demo Range",
"AllMup": false,
"Lines": [{
"Id": "0050560107dd",
"AllMup": false,
"Fields": [{
"Id": "0050560107dd",
"Name": "Category",
"IsRequired": false,
"Format": {
"Type": "Dictionary",
"Dictionary": {
"Name": "Some category",
"SysName": "LitigationCategory",
"ValuesUrl": "https://myempty.com",
"Id": "902b343a9588",
},
"CalForm": []
}
}]
}]
}
]

Related

How to get an array of object values embedded within an array of objects

I have an array that has objects, within which is an array of objects as shown below.
const property = [
{
houses: {
"id": "HT-00001",
"features": [{ "id": "FT-0001", "name": "balcony"}, { "id": "FT-0002", "name": "wifi"}],
"opts": [{
"desc": "House description",
"bed": 3,
"bath": 1,
"location": "Location of property",
"name": "Name of Property Listing",
"isDefault": false,
"listPrice": [{"amount": 123, "currency": "EUR"}]
}]
},
currency: {
"currency": "EUR"
}
},
{
houses: {
"id": "HT-00002",
"features": [{ "id": "FT-0003", "name": "tiled floor"}, { "id": "FT-0002", "name": "wifi"}],
"opts": [{
"desc": "House description",
"bed": 3,
"bath": 1,
"location": "Location of property",
"name": "Name of Property Listing",
"isDefault": false,
"listPrice": [{"amount": 123, "currency": "EUR"}]
}]
},
currency: {
"currency": "EUR"
}
},
{
houses: {
"id": "HT-00003",
"features": [{ "id": "FT-0004", "name": "refrigerator"}, { "id": "FT-0005", "name": "microwave"}],
"opts": [{
"desc": "House description",
"bed": 3,
"bath": 1,
"location": "Location of property",
"name": "Name of Property Listing",
"isDefault": false,
"listPrice": [{"amount": 123, "currency": "EUR"}]
}]
},
currency: {
"currency": "EUR"
}
},
];
Now, I am getting a challenge extracting a unique list of features name as an array. Take note that the features has objects and it is within houses object which is an object of object of the array that I am dealing with. What I want is just an array of all unique feature names that are within the provided property array. This is what I have tried, even though it is so much confusing and I need your help.
const allFeatures = property?.map((propertyItem) => {
let features = Array.from(new Set(propertyItem?.houses?.features?.map(({ name }) => name)));
return features;
});
The expected array will be something like:
allFeatures = ['balcony', 'wifi', 'tiled floor', 'refrigerator', 'microwave']
Iterate over each "house" object and, further, iterate over each features array within each object. You can use map for that inner iteration, but to get a resulting flattened array use flatMap for the outer iteration. You can then create a set from that, and then get the depuped array from that set.
(Note: in my experience if you put your code all on one line it makes it more difficult to debug.)
const property=[{houses:{id:"HT-00001",features:[{id:"FT-0001",name:"balcony"},{id:"FT-0002",name:"wifi"}],opts:[{desc:"House description",bed:3,bath:1,location:"Location of property",name:"Name of Property Listing",isDefault:!1,listPrice:[{amount:123,currency:"EUR"}]}]},currency:{currency:"EUR"}},{houses:{id:"HT-00002",features:[{id:"FT-0003",name:"tiled floor"},{id:"FT-0002",name:"wifi"}],opts:[{desc:"House description",bed:3,bath:1,location:"Location of property",name:"Name of Property Listing",isDefault:!1,listPrice:[{amount:123,currency:"EUR"}]}]},currency:{currency:"EUR"}},{houses:{id:"HT-00003",features:[{id:"FT-0004",name:"refrigerator"},{id:"FT-0005",name:"microwave"}],opts:[{desc:"House description",bed:3,bath:1,location:"Location of property",name:"Name of Property Listing",isDefault:!1,listPrice:[{amount:123,currency:"EUR"}]}]},currency:{currency:"EUR"}}];
const allFeatures = property.flatMap(obj => {
return obj.houses.features.map(feature => {
return feature.name;
});
});
const deduped = [...new Set(allFeatures)];
console.log(deduped);
As #andy has indicated Array#flatMap, Array#map and [...new Set(features)] is the way to go. Here, I'm using arrow functions and Object destructuring as well.
const property = [ { houses: { "id": "HT-00001", "features": [{ "id": "FT-0001", "name": "balcony"}, { "id": "FT-0002", "name": "wifi"}], "opts": [{ "desc": "House description", "bed": 3, "bath": 1, "location": "Location of property", "name": "Name of Property Listing", "isDefault": false, "listPrice": [{"amount": 123, "currency": "EUR"}] }] }, currency: { "currency": "EUR" } }, { houses: { "id": "HT-00002", "features": [{ "id": "FT-0003", "name": "tiled floor"}, { "id": "FT-0002", "name": "wifi"}], "opts": [{ "desc": "House description", "bed": 3, "bath": 1, "location": "Location of property", "name": "Name of Property Listing", "isDefault": false, "listPrice": [{"amount": 123, "currency": "EUR"}] }] }, currency: { "currency": "EUR" } }, { houses: { "id": "HT-00003", "features": [{ "id": "FT-0004", "name": "refrigerator"}, { "id": "FT-0005", "name": "microwave"}], "opts": [{ "desc": "House description", "bed": 3, "bath": 1, "location": "Location of property", "name": "Name of Property Listing", "isDefault": false, "listPrice": [{"amount": 123, "currency": "EUR"}] }] }, currency: { "currency": "EUR" } } ],
features = [...new Set(
property.flatMap(
({houses:{features}}) => features.map(({name}) => name)
)
)];
console.log( features );

How to insert values of matching JSON Keys between 2 JSON files

I have 2 JSON files:
A Template JSON
A JSON output (from awscli)
The template is a small JSON file as below:
{
"DryRun": true,
"ImageId": "",
"KeyName": "",
"SecurityGroups": [
""
],
"InstanceType": "",
"Monitoring": {
"Enabled": false
},
"SubnetId": "",
"DisableApiTermination": true,
"PrivateIpAddress": "",
"IamInstanceProfile": {
"Arn": "",
"Name": ""
},
"EbsOptimized": true,
"TagSpecifications": [{
"ResourceType": "",
"Tags": [{
"Key": "",
"Value": ""
}]
}]
}
The original file is the output of aws ec2 describe-instances:
{
"Reservations": [{
"OwnerId": "123456789012",
"ReservationId": "r-12345678",
"Groups": [],
"Instances": [{
"Monitoring": {
"State": "disabled"
},
"PublicDnsName": "ec2-12-34-56-78.ap-southeast-1.compute.amazonaws.com",
"RootDeviceType": "ebs",
"State": {
"Code": 16,
"Name": "running"
},
"EbsOptimized": false,
"LaunchTime": "2016-02-09T03:06:21.000Z",
"PublicIpAddress": "12.34.56.78",
"PrivateIpAddress": "172.31.1.2",
"ProductCodes": [],
"VpcId": "vpc-1a2b3c4d",
"StateTransitionReason": "",
"InstanceId": "i-abcd1234",
"ImageId": "ami-1234abcd",
"PrivateDnsName": "ip-172-31-1-2.ap-southeast-1.compute.internal",
"KeyName": "tempKey",
"SecurityGroups": [{
"GroupName": "somegroup1",
"GroupId": "sg-ZZZZZ"
},
{
"GroupName": "somegroup2",
"GroupId": "sg-YYYYY"
}
],
"ClientToken": "NutKc123456789012",
"SubnetId": "subnet-00001234",
"InstanceType": "t2.medium",
"NetworkInterfaces": [{
"Status": "in-use",
"MacAddress": "02:AA:BB:CC:DD:EE",
"SourceDestCheck": true,
"VpcId": "vpc-1a2b3c4d",
"Description": "",
"Association": {
"PublicIp": "12.34.56.78",
"PublicDnsName": "ec2-12-34-56-78.ap-southeast-1.compute.amazonaws.com",
"IpOwnerId": "123456789012"
},
"NetworkInterfaceId": "eni-XXXXXXXX",
"PrivateIpAddresses": [{
"PrivateDnsName": "ip-172-31-1-2.ap-southeast-1.compute.internal",
"Association": {
"PublicIp": "1.2.3.4",
"PublicDnsName": "ec2-12-34-56-78.ap-southeast-1.compute.amazonaws.com",
"IpOwnerId": "123456789012"
},
"Primary": true,
"PrivateIpAddress": "172.31.1.2"
}],
"PrivateDnsName": "ip-172-31-1-2.ap-southeast-1.compute.internal",
"Attachment": {
"Status": "attached",
"DeviceIndex": 0,
"DeleteOnTermination": true,
"AttachmentId": "eni-attach-XXXXXXXX",
"AttachTime": "2016-01-13T08:33:37.000Z"
},
"Groups": [{
"GroupName": "somegroup1",
"GroupId": "sg-ZZZZZZ"
},
{
"GroupName": "somegroup2",
"GroupId": "sg-YYYYYY"
}
],
"Ipv6Addresses": [],
"SubnetId": "subnet-00001234",
"OwnerId": "123456789012",
"PrivateIpAddress": "172.31.1.2"
}],
"SourceDestCheck": true,
"Placement": {
"Tenancy": "default",
"GroupName": "",
"AvailabilityZone": "ap-southeast-1b"
},
"Hypervisor": "xen",
"BlockDeviceMappings": [{
"DeviceName": "/dev/xvda",
"Ebs": {
"Status": "attached",
"DeleteOnTermination": true,
"VolumeId": "vol-33221100",
"AttachTime": "2016-01-13T08:33:39.000Z"
}
}],
"Architecture": "x86_64",
"StateReason": {
"Message": "Client.UserInitiatedShutdown: User initiated shutdown",
"Code": "Client.UserInitiatedShutdown"
},
"RootDeviceName": "/dev/xvda",
"VirtualizationType": "hvm",
"Tags": [{
"Value": "SomeValue",
"Key": "SomeKey"
},
{
"Value": "AnotherValue",
"Key": "Name"
}
],
"AmiLaunchIndex": 0
}]
}]
}
I want to copy the values of the Keys in the original JSON file to the template file.
For example, KeyName is a common key between the 2 JSON files. The corresponding value tempKey is replaced in the template file.
The main use case of this is: I am trying to migrate a number of servers on AWS from 1 region to another. This is a part of migration process which will remove tons of manual clicking and configuration on AWS Console.
Note: I use BASH command line.
There's a way to do this with jq but it doesn't take a JSON template as input.
You'll have to modify it to become a query. This isn't the actual query you need, but something to get you started:
cat temp.json | jq '.Reservations[].Instances[] | { DryRun, ImageId, KeyName, SecurityGroups, InstanceType, Monitoring }'
Where temp.json is your output above that I placed into a file. For regular commands, just do something like aws ec2 describe-instances | jq ...
The output that gives me (keep in mind the restricted set I queried for) is:
{
"DryRun": null,
"ImageId": "ami-1234abcd",
"KeyName": "tempKey",
"SecurityGroups": [
{
"GroupName": "somegroup1",
"GroupId": "sg-ZZZZZ"
},
{
"GroupName": "somegroup2",
"GroupId": "sg-YYYYY"
}
],
"InstanceType": "t2.medium",
"Monitoring": {
"State": "disabled"
}
}
Hope this helps.

How do I join multiple columns into one in footable?

I have a FooTable that gets a part number returned as 3 separate cells. I'd like to combine them into one cell but I'm unsure of how the formatter and parser work for FooTable. my table html is just an empty table, everything is handledin the javascript. How would I go about doing this?
$(document).ready(function() {
jQuery(function($){
$('.table').footable({
"expandFirst": false,
"columns": [
{ "name": "PartID", "title":"PartID", "visible":false },
{"formatter": function(value){
return //I'm thinking this is where the code would go to join the next 3 columns? in the format ##.###.##
}},
{ "name": "PartCategory", "title": "PC" },
{ "name": "PartNumber1", "title": "PN1" },
{ "name": "PartNumber2", "title": "PN2", },
{ "name": "PartName", "title": "Name", },
{ "name": "DescShort", "title": "Description", },
{ "name": "SupplierName", "title": "Supplier", },
{ "name": "SupplierPartNumber", "title": "Supplier Part #", }
],
"rows": $.getJSON("../dist/scripts/testGetParts.php")
});
});
});
You can simply add data-hide="all" to the first two columns of those three:
{ "name": "", "title": "", data-hide="all"},
{ "name": "", "title": "", data-hide="all"},
{ "name": "Part Info", "title": "Part Information" }
Merge those in php (which you are good at) and just show them in here as one col in your dataset and Voila.
The simpler version if you can change the dataset is to not add those columns at all.
Another option if you cannot/don't want to change your server side code is to get the data and change it js and then bind them to rows afterwards.
var rows = $.getJSON("../dist/scripts/testGetParts.php");
foreach(row in rows) {
//merge those cols here in the third one
}
And then:
jQuery(function($){
$('.table').footable({
"expandFirst": false,
"columns": [
{ "name": "PartID", "title":"PartID", "visible":false },
{ "name": "PartCategory", "title": "PC", data-hide="all" },
{ "name": "PartNumber1", "title": "PN1", data-hide="all"},
{ "name": "Part Info", "title": "Part information" },
{ "name": "PartName", "title": "Name", },
{ "name": "DescShort", "title": "Description", },
{ "name": "SupplierName", "title": "Supplier", },
{ "name": "SupplierPartNumber", "title": "Supplier Part #", }
],
"rows": rows
});
});
Not sure how you do it persay in footable, in kendo you would do it like so.
$(document).ready(function() {
jQuery(function($){
$('.table').footable({
"expandFirst": false,
"columns": [
{ "name": "PartID", "title":"PartID", "visible":false },
{ "title":"PartNumber", formatter: function(data){
return data.PartCategory +"."+ data.PartNumber1 +"." + PartNumber2;
}},
{ "name": "PartName", "title": "Name", },
{ "name": "DescShort", "title": "Description", },
{ "name": "SupplierName", "title": "Supplier", },
{ "name": "SupplierPartNumber", "title": "Supplier Part #", }
],
"rows": $.getJSON("../dist/scripts/testGetParts.php")
});
});
});

Passing function argument to retrieve data from an object

I am have some trouble with a script I am working on. I have been provided with an object with multiple items from a product catalog.
What I am trying to do is to write a function which to which will allow me to render this data easily.
<script type="application/javascript">
SKUinfo =
{
"s238554": {
"Age": {
"Description": "Age 18+",
"Thumbnail": "/productImages/assets/img/icon18.gif"
},
"Barcode": {
"Barcode": "50622132430794"
},
"Currency": "£",
"Description": "Description goes here",
"Id": 44305,
"Packshots": [
"/productImages/238556/1min.jpg",
"/productImages/238556/2med.jpg",
"/productImages/238556/3max.jpg"
],
"Pegis": [],
"Platform": {
"Button": "Xbox 360",
"ID": 0
},
"Publisher": {
"Description": null
},
"Release": "/Date(1392940800000+0000)/",
"Screenshots": [
{
"ScreenshotMax": "/productImages/238556/5scrmax1.jpg",
"ScreenshotMin": "/productImages/238556/4scrmin1.jpg"
}
],
"Title": "Product title 2 goes here",
"Variants": [
{
"Id": 58242,
"MaxOrderQuantity": 3,
"Presellable": true,
"Price": 29.97,
"PriceCultureFormat": "29.97",
"PriceWithCurrencyFormat": "£29.97",
"Sku": 238556,
"Type": {
"Description": "New"
}
},
],
"Vendor": {
"Description": ""
},
},
"s238556": {
"Age": {
"Description": "Age 18+",
"Thumbnail": "/productImages/assets/img/pegi/icon18.gif"
},
"Barcode": {
"Barcode": "5060134530794"
},
"Currency": "£",
"Description": "Description here",
"Id": 654654,
"Packshots": [
"/productImages/238556/1min.jpg",
"/productImages/238556/2med.jpg",
"/productImages/238556/3max.jpg"
],
"Pegis": [],
"Platform": {
"Button": "PlayStation 3",
"ID": 0
},
"Publisher": {
"Description": null
},
"Release": "/Date(1392940800000+0000)/",
"Screenshots": [
{
"ScreenshotMax": "/productImages/238556/5scrmax1.jpg",
"ScreenshotMin": "/productImages/238556/4scrmin1.jpg"
},
{
"ScreenshotMax": "/productImages/238556/7scrmax2.jpg",
"ScreenshotMin": "/productImages/238556/6scrmin2.jpg"
},
],
"Title": "Product title 2 goes here",
"Variants": [
{
"Id": 58242,
"MaxOrderQuantity": 3,
"Presellable": true,
"Price": 29.97,
"PriceCultureFormat": "29.97",
"PriceWithCurrencyFormat": "£29.97",
"Sku": 238556,
"Type": {
"Description": "New"
}
},
],
"Vendor": {
"Description": ""
},
"VideoHTML": "html here",
"status": {
"Response": "product found",
"Success": true
}
}
}
</script>
The above example is the output I get for two products.
If I try to get access to this data this is where I have a problem
<script type="application/javascript">
function getSKU(s)
{
console.log(SKUinfo.s.Title);
}
getSKU(s238554);
</script>
I imagine this is being caused when I am passing the argument s back to the function getSKU a the node selection in the data object. In this I would expect the console output to be the Title from SKU s238554.
What I get however, is: Uncaught ReferenceError: s238554 is not defined
I would appreciate any guidance that can be offered as I am a javascript novice.
Access your property by used[] on SKUinfo.s.Title like SKUinfo[s].Title
And also pass your property name within the quotes 's238554' as it's not variable.
Something like this.
function getSKU(s){
console.log(SKUinfo[s].Title);
}
getSKU('s238554'); // s238554 within quotes.

metadata configuration of fields in ExtJS DirectStore

I am trying to load grid data from a ExtDirect router. The results contain a metaData object that should reconfigure the store's fields. I am getting the following error however when I try to load my data:
Uncaught TypeError: Cannot read property 'sortType' of undefined (ext-all-debug.js:23943)
The JSON result is:
{
"action": "Dashboard",
"method": "dashboarddata",
"type": "rpc",
"result": {
"success": true,
"metaData": {
"sortInfo": {
"direction": "ASC",
"field": "id"
},
"fields": [{
"mapping": "id",
"id": "id"
},
{
"mapping": "owner",
"id": "owner"
},
{
"mapping": "name",
"id": "name"
},
{
"mapping": "type",
"id": "type"
},
{
"mapping": "strategy",
"id": "strategy"
},
{
"mapping": "primebroker",
"id": "primebroker"
},
{
"mapping": "startdate",
"id": "startdate"
},
{
"mapping": "date_afc_prelim_approval",
"id": "date_afc_prelim_approval"
},
{
"mapping": "date_afc_approval",
"id": "date_afc_approval"
},
{
"mapping": "date_submit_regulator",
"id": "date_submit_regulator"
},
{
"mapping": "date_approval_regulator",
"id": "date_approval_regulator"
},
{
"mapping": "enddate",
"id": "enddate"
},
{
"mapping": "main_iso_currency",
"id": "main_iso_currency"
},
{
"mapping": "nav_frequency",
"id": "nav_frequency"
},
{
"mapping": "date_first_nav",
"id": "date_first_nav"
},
{
"mapping": "launch_size",
"id": "launch_size"
},
{
"mapping": "target_size",
"id": "target_size"
},
{
"mapping": "memo",
"id": "memo"
},
{
"mapping": "isin_codes",
"id": "isin_codes"
},
{
"mapping": "status",
"id": "status"
}],
"totalProperty": "total",
"successProperty": "success",
"idProperty": "id",
"root": "data"
},
"data": [{
"status": "Project closed",
"strategy": "Strategy X",
"date_afc_approval": "2010-01-01",
"startdate": "2010-01-01",
"nav_frequency": "Bi-monthly",
"date_first_nav": "2010-01-01",
"enddate": "2010-01-01",
"date_approval_regulator": "2010-01-01",
"id": "1",
"date_afc_prelim_approval": "2010-01-01",
"isin_codes": "123",
"target_size": "2000",
"owner": "Some name",
"name": "First project",
"memo": "TEXTEXTEXT",
"main_iso_currency": "TND",
"primebroker": "Yes",
"date_submit_regulator": "2010-01-01",
"launch_size": "1000",
"type": "TypeX"
}],
"total": 1
},
"tid": 6
}
The store itself is configured like:
var store = new Ext.data.DirectStore({
idProperty: 'id'
,paramsAsHash: true
,directFn: MyApp.Direct.Dashboard.dashboarddata
,root:'data'
,autoLoad: false
,totalProperty:'total'
,fields: [
{name: 'id', mapping: 'id'},
{name: 'type', mapping: 'type'}
]
,baseParams: {
type: this.type,
filters: this.filters
}
});
Can anyone please help me? This is driving me nuts, I cannot see what I am doing wrong.
Thanks!
Rob
PS. I am using ExtJS 3.3.0
Why not debug that place using Chrome or Firefox debug facility? The helpful options is setting the break on exception in the Chrome.
I fixed it. Debugging did the trick.
Apparently when updating the fields through the metaData object in the JSON response you need to name the fields. ExtJS uses the name field as a lookup field internally. Strange thing is that with static configuration of a store's fields you don't need that field...
...
"fields": [{
"mapping": "id",
"name": "id",
"id": "id"
},
{
"mapping": "owner",
"name": "owner",
"id": "owner"
},
...

Categories

Resources