Suppose I have several nested objects(human1, human2, human3) in "human" object.
human: {
"human1": {
"name" : "John",
"sex" : "male",
"age" : 18
}
"human2": {
"name" : "Peter",
"sex" : "male",
"age" : 16
}
"human3": {
"name" : "May",
"sex" : "female",
"age" : 19
}
}
And I have another object called currentPlayer below, which I want it to be a vessel, in order to access the data from "human1", "human2", or "human3" for different use.
currentPlayer: {
"name" : "default",
"sex" : "default",
"age" : 0
}
Example: today I want currentPlayer to be John, and it goes
currentPlayer: {
"name" : "John",
"sex" : "male",
"age" : 18
}
And then I want currentPlayer to be Peter, and it goes:
currentPlayer: {
"name" : "Peter",
"sex" : "male",
"age" : 16
}
How do I iterate property values of currentPlayer like this with loop, not just key in one by one? Thanks...
Bellow code will iterate through all Properties of human object
listofhuman = Object.getOwnPropertyNames(human);
var currentPlayer;
for (var objHumanName in listofhuman) {
if (listofhuman[objHumanName].Name === "Jonh") {
currentPlayer = Object.create(listofhuman[objHumanName]);
break;
}
}
at the end of this loop you will get human which you wonted
if you do Object.getOwnPropertyNames(currentPlayer) this will return array of string which are the actual keys in object currentPlayer, and you can access those values by currentPlayer[arryofProp[0]]
Related
I am looking for alternative ways to parse a JSON tree. Given the following example:
{
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}
}
if I am trying to access branches, such as address.streetAddress or address.city then I can see two ways of getting that value:
1) JSON Path with the queries listed above
2) Manually split the query into "branches" (main branch address, sub-branch streetAddress) then check the object keys that way.
Are there any better ways of doing this? And by better I mean efficient, not necessarily "clean" in terms of code.
The application of said code would be to use this within an NGRX metareducer to automatically save the object to localstorage, so it is potentially going to be evaluating a large tree very often.
Thanks.
After some testing of various methods I ended up selecting _ug's answer.
Data below, as well as a gist of the script I used (sans data, which was sensitive). I ran each function 1 million times over 4 queries.
Executing test: empty test
Average time for 1,000,000 executions: 6.181699991226196 milliseconds.
Executing test: split and reduce
Average time for 1,000,000 executions: 429.71359902620316 milliseconds.
Executing test: lodash
Average time for 1,000,000 executions: 1091.8809990286827 milliseconds.
Executing test: json path
Average time for 1,000,000 executions: 32114.680999994278 milliseconds.
You can use lodash _.property method to do so:
https://lodash.com/docs/4.17.15#property
const _ = require('lodash');
let obj = {
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}
}
console.log(_.property('address.streetAddress')(obj));
// Or
console.log(_.propertyOf(obj)('address.streetAddress'));
Coincidentally just wrote something for this, it doesn't work for arrays but is very simple.
let obj = {
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"address" : {
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}
}
function jsonPath(path, obj) {
return path.split('.').reduce((o, p) => o[p], obj);
}
console.log(jsonPath('address.streetAddress', obj));
console.log(jsonPath('address.city', obj));
You could also adapt it to run with arrays by changing the split to handle brackets split(/[\[\.\]]+/)
You can also make it return undefined instead of throwing an error when a path value is not found by changing the reduce to reduce((o, p) => o && o[p], obj)
Result would be:
let obj = {
"firstName": "John",
"lastName" : "doe",
"age" : 26,
"addresses" : [{
"streetAddress": "naist street",
"city" : "Nara",
"postalCode" : "630-0192"
}]
}
function jsonPath(path, obj) {
return path.split(/[\[\.\]]+/).reduce((o, p) => o && o[p], obj);
}
console.log(jsonPath('addresses[0].streetAddress', obj));
console.log(jsonPath('addresses[0].city', obj));
console.log(jsonPath('addresses[2].city', obj));
This question already has answers here:
Convert a JavaScript string in dot notation into an object reference
(34 answers)
Closed 3 years ago.
I'm trying to extract some of the fields from a Json response and push them into a Javascript array. I want the selection of the fields to be configurable. Here is what I'm doing:
Consider this as my JSON string:
{
"id" : "1234",
"orderNumber" : "1196",
"createdOn" : "2019-07-02T12:03:39.697Z",
"modifiedOn" : "2019-07-02T12:25:52.126Z",
"testmode" : false,
"customerEmail" : "a#b.com",
"billingAddress" : {
"firstName" : "John",
"lastName" : "Doe",
"address1" : "Wall Street",
"address2" : null,
"city" : "NYC",
"state" : "NY",
"countryCode" : "US",
"postalCode" : "12345",
"phone" : "1122334455"
}
}
Say I want to extract some of the fields (defined in the FIELDS variable) and push them in an array.
# NOTE: the variable `data` here is my json object
var FIELDS = ['id', 'orderNumber', 'customerEmail', 'billingAddress.firstName', 'billingAddress.lastName']
var lineItem = []
# parse the data (my Json object)
for (var i = 0; i < FIELDS.length; i++){
lineItem.push(data[FIELDS[i]])
}
So, this seems to be working OK for the first level (the id, orderNumber and customerEmail) but not for the billingAddress.firstname, etc. This is what I'm wondering about.
My intent is to be able to modify the definition in the FIELDS variable without needing to make any change to the logic in the code.
Hope this makes sense.
Thanks!
As long as there are no periods in the key names this will work.
var data = {
"id" : "1234",
"orderNumber" : "1196",
"createdOn" : "2019-07-02T12:03:39.697Z",
"modifiedOn" : "2019-07-02T12:25:52.126Z",
"testmode" : false,
"customerEmail" : "a#b.com",
"billingAddress" : {
"firstName" : "John",
"lastName" : "Doe",
"address1" : "Wall Street",
"address2" : null,
"city" : "NYC",
"state" : "NY",
"countryCode" : "US",
"postalCode" : "12345",
"phone" : "1122334455"
}
};
var FIELDS = ['id', 'orderNumber', 'customerEmail', 'billingAddress.firstName', 'billingAddress.lastName'];
var lineItem = [];
for (var i = 0; i < FIELDS.length; i++){
let obj = data;
let parts = FIELDS[i].split(".");
while(parts.length) obj = obj[parts.shift()];
lineItem.push(obj)
}
console.log(lineItem);
You just need a function that will split that path on . and traverse the JSON data. With that you can just map() over your fields.
let data = {"id" : "1234","orderNumber" : "1196","createdOn" : "2019-07-02T12:03:39.697Z","modifiedOn" : "2019-07-02T12:25:52.126Z","testmode" : false,"customerEmail" : "a#b.com","billingAddress" : {"firstName" : "John","lastName" : "Doe","address1" : "Wall Street","address2" : null,"city" : "NYC","state" : "NY","countryCode" : "US","postalCode" : "12345","phone" : "1122334455"}}
var FIELDS = ['id', 'orderNumber', 'customerEmail', 'billingAddress.firstName', 'billingAddress.lastName']
// split an traverse
const getFromPath = (path, data) => path.split('.')
.reduce((curr, p) => curr && curr[p], data) // check for curr incase path is undefined
console.log(FIELDS.map(p => getFromPath(p, data)))
The function getFromPath will return undefined if any part of the traversal is not found in the object.
This is my first time using lodash and I'm trying to figure out how to update each record within a JSON object. For example, let's say I have a person object:
"person":[
{
"firstName" : "Alex",
"lastName" : "Smith"
},
{
"firstName" : "Madison",
"lastName" : "Matthews"
}
]
I would like to add a new field called "fullName" to each record in person that is a combination of their first and last names. Is there a way I can do this using lodash and/or javascript? I don't want to use any other tool.
Thanks!
Here if you have persons collection(Array of json objects) then you can add one more property by traversing the collection with lodash function. There are other several ways also.
var persons = [
{
"firstName" : "Alex",
"lastName" : "Smith"
},
{
"firstName" : "Madison",
"lastName" : "Matthews"
}
];
var personsWithFullName = _(persons).forEach(function(person) {
person.fullName = person.firstName + person.lastName;
return person;
});
or
var newPersonsWithFullName = _.map(persons , function(person) {
return _.assign({}, person, {fullName: (person.firstName + person.lastName)});
});
I create an array of Objects from a database query and call the
array jobListRecords. There are multiple records in the array created that have the same "customerID" and "name".
I would like to create a new array that has one record for each customer with a new field , "jobArray", that contains another array of all of that customers services. (see sortCustomer array down below)
An example of the initial array:
jobListRecords = [
{
"customerID" : "1",
"name" : "Larry Bird",
"serviceID" : "101",
"serviceName" : "Dog Walking"
},
{
"customerID" : "2",
"name" : "Andrew Luck",
"serviceID" : "202",
"serviceName" : "Baby Sitting"
},
{
"customerID" : "2",
"name" : "Andrew Luck",
"serviceID" : "101",
"serviceName" : "Dog Walking"
}
]
Desired Result
sortCustomer Example:
sortCustomer = [
{
"customerID" : "1",
"name" : " Larry Bird",
"jobArray" : [
{
"serviceID" : "101",
"serviceName" : "Dog Walking"
}
]
},
{
"customerID" : "2",
"name" : "Andrew Luck",
"jobArray" : [
{
"serviceID" : "202",
"serviceName" : "Baby Sitting"
},
{
"serviceID" : "101",
"serviceName" : "Dog Walking"
}
]
}
Is their a simple or efficient way of solving this without having to iterate through all the data 3+ times. Thank You for your time, below is one of the several things I tried.
I tried solving this using one example I found but it grouped all the serviceIDs together which is not what I need.
Example that DID NOT work that I tried.
jobListGrouped = _
.chain(jobListRecords)
.groupBy('customerID')
.map(function(value, key) {
return {
CustomerID: key,
services: _.pluck(value, 'serviceID')
}
})
.value();
You're plucking only the serviceIDs into that array. Instead, you would need to do something like
.map(function(values, key) {
return {
customerID: key,
name: values[0].name.
services: _.map(values, _.partial(_.pick, _, 'serviceID', 'serviceName'))
}
})
or even more explicit
.map(function(values, key) {
return _.extend(_.omit(values[0], 'serviceID', 'serviceName'), {
services: _.map(values, _.partial(_.pick, _, 'serviceID', 'serviceName'))
}
})
(where that partial call is the same as function(value) { return _.pick(value, 'serviceID', 'serviceName'); })
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How do I create Javascript array(JSON format) dynamically?
I am attempting to create the following:
var employees = {"accounting": [ // accounting is an array in employees.
{ "firstName" : "John", // First element
"lastName" : "Doe",
"age" : 23 },
{ "firstName" : "Mary", // Second Element
"lastName" : "Smith",
"age" : 32 }
] // End "accounting" array.
} // End Employees
I started out with:
var employees=new Array();
How do I continue to append to the array dynamically (might change firstName with variable)?
var employees = {accounting: []};
employees.accounting.push({
"firstName" : "New",
"lastName" : "Employee",
"age" : 18
});
employees.accounting.push({ "firstName" : "New", // First element
"lastName" : "Person",
"age" : 55 });
var urNewFirstName='new john';
employees.accounting[0].firstName = urNewFistName;
function Employee(firstName, lastName, age) {
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
}
var employees = {};
employees.accounting = [];
employees.accounting.push(new Employee('John', 'Doe', 23));
employees.accounting.push(new Employee('Mary', 'Smith', 32));