This question already has answers here:
Convert a JavaScript string in dot notation into an object reference
(34 answers)
Closed 3 years ago.
So say that I have an array of objects with objects within the objects. This data is dynamic, i.e the keys wont be the same , it may differ.
For example:
[
{
"uuid": "53e7202c-28c8-4083-b910-a92c946a7626",
"extraIdentifiers": {
"National ID": "NAT2804"
},
"givenName": "Krishnan",
"customAttribute": null,
"age": "32"
},
{
"uuid": "9717ec58-8f87-4305-a57b-bed54301def7",
"extraIdentifiers": {
"National ID": "NAT2805"
},
"givenName": "Dale",
"customAttribute": null,
"age": "32"
},
{
"uuid": "d3563522-927d-4ff0-b697-eb164289a77d",
"extraIdentifiers": {
"National ID": "NAT2806"
},
"givenName": "David",
"age": "32"
}
]
Now I have a function which will get the value from one of the keys. For eg , I want to get the givenName so it will return David for example.
This is the code for it:
$scope.sortPatient = function (param) {
$scope.results.map(function (currentObj) {
console.log(currentObj[param]);
})
};
The $scope.results will hold the above JSON Obj. When calling sortPatient I would call it by passing the key whose value I want. For eg: sortPatient('givenName') or sortPatient('age').
This would log Dale or 32 in the console. But if I call sortPatient('extraIdentifiers.National ID') it does not log NAT2804 in the console, but logs undefined. I also tried calling it like sortPatient('extraIdentifiers[National ID]') but it still shows undefined.
How would I be able to get the values of keys inside keys? I also cannot change the way the function is being called. I can only change its definition., but I'm not able to get the values of keys inside complex objects.
I would pass an array with keys to your method instead, and then check if the object contains the given key path.
$scope.sortPatient = function (params) {
$scope.results.map(function (currentObj) {
var res = currentObj;
params.forEach(function(param){
if(res[param]) res = res[param];
})
console.log("res",res);
})
};
$scope.sortPatient(['extraIdentifiers','National ID']);
Related
This question already has answers here:
Accessing nested JavaScript objects and arrays by string path
(44 answers)
Closed 6 months ago.
I am trying to read values from JSON Object using a function that is dynamic.
Sample JSON Object -
var test =
{
"test1": {
"test2": "value2"
},
"test3": {
"test4": {
"test5": "value5"
}
}
}
Now I need to read the test5 value and test2 value so I created the below method and called it twice by passing the argument.
readValue('test1.test2');
readValue('test3.test4.test5');
function readValue(val){
console.log(eval(`test.${val}`));
}
This code is working fine, I am able to get the output.
But is there any alternative to use eval here ??
Better than eval, split your compound key by a dot and iterate it:
let val = (obj, keys) => keys.split('.').reduce(Reflect.get, obj)
var test =
{
"test1": {
"test2": "value2"
},
"test3": {
"test4": {
"test5": "value5"
}
}
}
console.log(val(test, 'test1.test2'))
console.log(val(test, 'test3.test4.test5'))
This question already has answers here:
Accessing a JavaScript's object property without knowing that property name
(3 answers)
How to access the first property of a Javascript object?
(23 answers)
Getting the first index of an object
(14 answers)
Closed 3 years ago.
I'm calling an API in my application and need to drill down the JSON response. Within it there is a random string that changes so I can't hardcode the value. Is there a way I can access dataset1 no matter what the random string is?
{
"data": {
"Random String that Changes": {
"dataset1": {
"date": {...}
},
"dataset2":{
"date": {...}
}
}
},
"something else": {
...
},
"something else": {
...
}
}
Previously I was hard coding the drill down like such:
this.props.data.randomData['Random String that Changes'].dataset1.date
Also tried:
this.props.data.randomData[0].dataset1.date
You can get all the keys of the object using
const keys = Object.keys(this.props.data);
Now keys is an array of all keys , but if you json always only has 1 key, you can get your data using
this.props.data.randomData[keys[0]].dataset1.date
You can get dataset1
const values = Object.values(this.props.data)
console.log(values[0]['dataset1'])
Make sure that your json includes the "Random String that changes" at first place as shown in your above format.
Reference: Object.values
Try accessing the object like this :
const obj = this.props.data;
obj[Object.keys(obj)[0]].dataset1.date
Reference: How to access the first property of an object in Javascript?
Consider sample data in myObj.
var myObj = {
"data" : {
"Random String that Changes": {
"dataset1": {
"date": "123"
},
"dataset2":{
"date": "123"
}
}
}
}
var randomString =myObj[Object.keys(myObj)[0]];
var dataset1Date =randomString[Object.keys(randomString)[0]].dataset1.date;
console.log(dataset1Date);
So in this way you can access the date which you are trying with
this.props.data.randomData['Random String that Changes'].dataset1.date
Please check the below code for the solution.
var response = {
"data": {
"Random String that Changes": {
"dataset1": {
"date": {...}
},
"dataset2":{
"date": {...}
}
}
},
"something else": {
...
},
"something else": {
...
}
};
var dataInRandomKey = response.data[Object.keys(response.data)[0]];
Now, you have the whole JSON object (in current example, response['data']['Random String that Changes']) in dataInRandomKey variable.
You can try for in loop
var a = {
"data": {
"Random String that Changes": {
"dataset1": {
"date": {...}
},
"dataset2":{
"date": {...}
}
}
},
"something else": {
...
},
"something else": {
...
}
}
var response = a.data;
for(var key in response) {
console.log(response[key].dataset1);
}
I would like to be able to iterate through and access the 'name' field values of an avro schema but have not been able to find an efficient way of doing so without getting extra values due to the particular way avro expects its schema data.
I can recursively iterate through it as though it were a js object; however, I end up with certain fields I did not want being included in my results.
For example, in the below code the only value I want to get back is 'foobar' however I also get 'Foo' which I do not want as that is the name of an array of objects rather than a single value.
{
"type": "record",
"name": "Foo",
"fields": [
{
"name": "foobar",
"type": "string"
}
]
}
The current function I am using looks like this:
iterateAvro = (target) => {
let result = [];
Object.entries(target).forEach(([key, val]) => {
if (val === null){
return null
}
if (typeof val === 'object'){
result = result.concat(this.iterateAvro(val));
} else {
if(key === 'name'){
result.push(val)
}
}
})
return result
}
I am new to avro (and coding in general) and do not know if there is an avro specific way of doing this. Any help would be appreciated.
What you are doing in your function is:
Convert a JavaScript object into an array of key/value pairs.
Iterating through the pairs and:
a. If the value is null do nothing.
b. If the value is an object, apply this logic to it using recursion.
c. If the key is name push the value to an array called result accessed through a Clojure.
Your function is grabbing any value whose key is name. That is why both foobar and Foo are returned.
Looking at Apache Avro's documentation I see that inside the fields key, there is a list with multiple field objects, each of which must have a name key.
So, assuming that you would like to get the values of all the field names you could do something like this:
// JSON object gotten directly from Apache Avro's documentation.
var avroRecord = {
"type": "record",
"name": "LongList",
"aliases": ["LinkedLongs"], // old name for this
"fields" : [
{"name": "value", "type": "long"}, // each element has a long
{"name": "next", "type": ["null", "LongList"]} // optional next element
]
}
function getFieldsNames(record) {
return avroRecord.fields.map((field) => {
return field.name;
});
}
console.log(getFieldsNames(avroRecord))
// [ 'value', 'next' ]
I hope this helps.
I'm trying to remove an object from Json Object it works..but it replace it with null..i dont know why, how can i remove the null value from the json..heres the function :
company.deleteExternalLinkFromGrid = function (row, matricule) {
// console.log('Inside of deleteModal, code = ' + code);
//$scope.sitting= {};
console.log(matricule);
//console.log(JSON.stringify(linkJsonObj));
delete linkJsonObj[matricule];
console.log(JSON.stringify(linkJsonObj));
};
heres the object:
[{"name":"xxx","link":"www.ddd.com","id":0,"$$hashKey":"uiGrid-001Z"},null,null]
You can use filter(), x will be without null's.
function test()
{
var x =[{"name":"xxx","link":"www.ddd.com","id":0,"$$hashKey":"uiGrid-001Z"},null,null].filter(isNotNull);
alert(JSON.stringify(x));
}
function isNotNull(value) {
return value != null;
}
fiddle
There are multiple ways to delete an object from an array of objects in JavaScript. You don't need AngularJS for that, you can use VanillaJS.
If you just want the nulls filtered you can use
var yourArray =[{"name":"xxx","link":"www.ddd.com","id":0,"$$hashKey":"uiGrid-001Z"},null,null];
yourArray = yourArray.filter(function(elt){
return elt != null;
});
But this loses the original reference to your object.
If you want to keep the reference, Use array.splice().
yourArray.forEach(function(){
yourArray.splice(yourArray.indexOf(null),1);
});
now you will have null less array in yourArray. This actually deletes an object from an array without changing the reference,
delete will replaced the object with undefined
You can filter the array to remove them using Array#filter()
var array = [{
"name": "xxx",
"link": "www.ddd.com",
"id": 0,
"$$hashKey": "uiGid-001Z"
}, {
"name": "xx",
"link": "www.dddcom",
"id": 1,
"$$hashey": "uiGrid-0029"
}, {
"name": "xxx",
"link": "www.ddd.com",
"id": 2
}];
delete array[1];
array = array.filter(a=>a);
console.log(JSON.stringify(array));
I have a JSON object with two arrays of an object x.
I'm using angularJS and I want to add/edit/delete objects in the JSON (just like the Angular TODO app example on angular.org).
Is there a way to create a new empty (with the structure of x but no values) JSON object of x, and simply push that to the above JSON object array?
How do I go about creating an empty value JSON object of x?
My Sample object x is (I nullified all the values) pasted below. So my JSON is just an array of these objects. In Angular, I want the user to fill out a form and hold the data in an empty object of this type and push it to the array. That's my goal.
Sample JSON
[{
"id": null,
"title": "",
"date": {},
"billPayerId": null,
"notes": "Sample Notes",
"billFinances": {
"billPayerId": null,
"billItemEntry": [
{
"itemDescriptionId": 1,
"itemDescription": "",
"userIdAndLiableCost": [
{
"userId": null,
"liableCost": null
},
{
"userId": null,
"liableCost": null
}
]
},
{
"itemDescriptionId": null,
"itemDescription": "",
"userIdAndLiableCost": [
{
"userId": null,
"liableCost": null
},
{
"userId": null,
"liableCost": null
}
]
}
],
"billTotal": null
},
"groupId": null
}];
You can use an object literal to store whatever you want. It is just a bag of properties (i.e. name) and values. e.g. var order = {};
Then an array literal could be used to hold the orders. e.g var orders = []; orders.push(order); But it would be just as easy to use another object literal with the id as a property.
But it seems like you want some sort of validation. Perhaps something to manage the order data and handle the validation, etc. Like so:
orderManager.dataStore = {
_data: {},
//_redundantData = []; //could easily store in an array if id isn't unique
get: function (id) {
return this._data[id];
},
getAll: function () {
return this._data;
},
set: function (id, order) {
validateOrder(order);
this._data[id] = order;
},
clear: function (id) {
this._data[id] = undefined;
},
add: function (order) {
validateOrder(order);
this._data[order.id] = order;
},
assertNotNull: function (data, key) {
if(data[key] == undefined) {
throw new Error("Key Missing: " + key + " for " + data.name);
}
},
validateOrder: function(order) {
assertNotNull(order,"id");
assertNotNull(order,"title");
//etc
},
containsOrder: function (id) {
for(var i=0;i<array.length;i++) {
if(array[i].id === id) {
return true;
}
}
return false;
}
};
If I'm reading all of this right, I think you may be misunderstanding how Angular works. You don't have to create an empty object for Angular to use within a form. As long as your form's inputs use dot notation, it will generate the object for you as the user fills in the inputs with data.
E.g.
<form>
<input type="text" ng-model="myForm.name">
<input type="text" ng-model="myForm.email">
<input type="text" ng-model="myForm.nickname">
</form>
Since we used the dot notation in the ng-model attribute, it creates the object for us as the user fills out the form. The generated object would look like this after the inputs are completed:
$scope.myForm = {
name: 'Justin',
email: 'justin#email.com',
nickname: 'Cerebrl'
};
Now, normally once the user clicks save, you'd send the data to the server for persistence and you could then just empty the object (e.g. $scope.myForm = {};) to reset the form. But, for some reason, you want to build an array first, then send the whole thing to the server when fully complete (at least that's how I'm understanding it).
To do this, you have to get around the fact that Objects and Arrays in JavaScript are reference types, so you can't push the object full of data to an array, and then empty the object to reset the form as that would then empty the object within the array as well, blowing your data store.
I would personally address this problem with Angular's object copy method (e.g. angular.copy(source);) seen here: http://docs.angularjs.org/api/angular.copy This allows you to make a non-referenced copy of an object and use it without mutating the original object. So, within the "save function", you would have this:
var myNewObj = angular.copy($scope.myForm);
myDataArray.push(myNewObj);
$scope.myForm = {};
That way, you've saved the completed form data, pushed it to the array and cleared the form's input data. Does this answer your question?