I have an object and I’m trying to find a specific value using an ID in ECMAScript6.
I’ve tried something like this: myvalue = this.json.find(x => x == '1234');
The JSON looks something like this:
{
"results": [
{
"abcde1234": {
"value": 4
}
},
{
"zxcv4567": {
"value": 2
}
}
]
}
All the examples I’ve found can only find off named key-value pairs.
Try
json.results.find(x => /1234/.test(Object.keys(x)[0]));
json = {
"results": [
{
"abcde1234": {
"value": 4
}
},
{
"zxcv4567": {
"value": 2
}
}
]
}
let r = json.results.find(x => /1234/.test(Object.keys(x)[0]));
console.log(r);
const json = {
'1234': { 'value' : 4},
'5678': { 'value' : 10}
};
const value = json['1234'];
console.log(value);
The JSON data doesn't seem proper.
But in case you are finding by key, you can directly access this, something like:
Parsed JSON maps directly to JavaScript types: Object, Array, boolean, string, number, null. Your example used find() which is (normally) a method used with arrays. If your JSON was structured like this, you could expect to use find:
const jsonString = '["a", "b", "c"]';
const jsonData = JSON.parse(jsonString);
jsonData.find(x => x === "a"); // "a"
But it seems like your data is structured as an object, so you can use normal property access:
const jsonString = '{"1234": {"value": 4}, "5678": {"value": 10}}';
const jsonData = JSON.parse(jsonString);
jsonData["1234"] // {value: 4}
jsonData["1234"].value // 4
EDIT
OP changed the data example, so the above code is less directly applicable, but the general point is: once you parse it, it's just javascript.
Related
I am querying the database using findOne which will return just one document. Now, I want a few of the fields of that document in one object and the other fields in the other object, both of which are wrapped in a single object. For example I have a table called Bus with the following fields -
_id,
busNo,
city,
agency,
date,
ticketPrice,
helper,
driver,
totalCollection
My find one query returns one document but I want it in the below format -
existingAggr - {
"result": [
{
"_id": "630dcd0c652489bca1b319f7",
"busNo": "123",
"city": "32",
"agency": "58",
"date": "2022-08-29T00:00:00.000Z",
}
],
"aggregates": {
"ticketPrice": 8,
"totalCollection": 402,
"helper": 0,
"driver": 23,
}
}
I want this either with single access of database, or we can do some javascript calculations to further bring my result in this manner, but I cant seem to reach the solution. Currently, I am using the below code -
const res = await Bus.findOne(
{ busNo, date },
{
_id :1,
busNo:1,
city:1,
agency:1,
date:1,
ticketPrice:1,
helper:1,
driver:1,
totalCollection:1
}
);
This would return all the fields in one.
Given a result, you can straightfowardly create new objects from your result.
const res = await BusDayWise.findOne(
{ ...filter },
{ session: mongoSession }
);
const result = [
{
"_id": res._id,
"busNo": res.busNo,
"city": res.city,
"agency": res/agency,
"date": res.date,
}
],
const aggregates =
{
"ticketPrice": res.ticketPrice,
"totalCollection": res.totalCollection,
"helper": res.helper,
"driver": res.driver,
}
More advanced answer
You can have a function that retrieve only certain key from a dictionnary
function subDict(dict, keys){
const newDict = {};
keys.forEach(key => newDict[key] = dict[key]);
return newDict
}
test = {"a": 1, "b": 2, "c": 3}
keys = ["a", "c"];
newTest = subDict(test, keys); // {"a": 1; "c": 3}
So in your case
const result = subDict(res, ["_id", "busNo", "city","agency", "date"]);
const aggregates = subDict(res, ["ticketPrice", "totalCollection", "helper", "driver"]);
This should be pretty straightforward to do with projection which is the act of transforming the shape of the documents.
Your edited question now includes a reference to the simplest type of projection, but there are many more. In your case it looks like you can still use a relatively simple one, try this:
{
"result._id": "$_id",
"result.busNo": "$busNo",
"result.city": "$city",
"result.agency": "$agency",
"result.date": "$date",
"aggregates.ticketPrice": "$ticketPrice",
"aggregates.totalCollection": "$totalCollection",
"aggregates.helper": "$helper",
"aggregates.driver": "$driver",
_id: 0
}
Playground demonstration here.
If you are going to be doing this every time you retrieve the data then you may wish to change the schema of the documents as they are stored in the database. Alternatively, you could create a view that defines this projection which would then be automatically applied every time you query the data and not have to rely on the client to request it.
I have a JSON object that will sometimes be an object (a single instance) and sometimes be an array (multiple instances of the object). I need to write an if statement that basically says if this section of JSON is an object, wrap it in an array containing that single object, and if it's an array containing multiple objects, return that array. In either instance I'm returning an array containing either 1 or multiple objects.
Here is what the JSON looks like when it is NOT an array.
"link": {
"values": {
"key1": "value1",
...
"key8": "value8"
},
"key9": "value9"
}
And it should look like this when it's an array:
"link": [{
"values": {
"key1": "value1",
...
"key8": "value8",
},
"key9": "value9"
}]
EDIT -----------------------------
This is what I've written so far that is producing the type error I'm experiencing.
const isLinkArray = sections.values;
isLinkArray.link = Array.isArray(isLinkArray.link) ? isLinkArray.link : [isLinkArray.link];
EDIT 2 ---------------------------
The final answer ended up being almost identical to Kinglish' answer, so I figured I would post it here. The issue I ran into was that the JSON right above 'link' was also an array and that was causing the typescript error.
const sectionsWithLinkArray = sections.map((section) => {
return {
values: {
...section.values,
link: !Array.isArray(section.values.link) ? [section.values.link] : section.values.link,
},
};
});
You can use Array.isArray to check, then convert
let data = {
"link": {
"values": {
"key1": "value1",
"key8": "value8"
},
"key9": "value9"
}
}
data.link = Array.isArray(data.link) ? data.link : [data.link];
console.log(data)
This can be done by writing a simple function that checks if it's an array.
const returnArray = (value) => {
if (Array.isArray(value) {
return value;
}
return
}
updated the answer of #Kinglish to typescript one because you cannot change types of defined value as it giving error for this either simply ignore the typescript or define types that simply accept link in object and array of object or just created new variable that expect a link in the array and wrap it inside data by simply doing this:
const data = {
link: {
values: {
key1: 'value1',
key8: 'value8',
},
key9: 'value9',
},
};
// This is the type of data you can't change it by default and it doesn't expect array of object of `link`.
// const data: {
// link: {
// values: {
// key1: string;
// key8: string;
// };
// key9: string;
// };
// };
const linkArray = { link: Array.isArray(data.link) ? data.link : [data.link] };
// Now this is the type of linkArray that expect array of object of `link`
// const linkArray: {
// link: {
// values: {
// key1: string;
// key8: string;
// };
// key9: string;
// }[];
// };
console.log('data', data);
console.log('linkArray', linkArray);
So I am pretty new when it comes to Javascript and it is as simple as read a json list with a value of:
{
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
What I would like to do is to have both the URL and the amount of numbers etc
"https://testing.com/en/p/-12332423/" and "999"
and I would like to for loop so it runs each "site" one by one so the first loop should be
"https://testing.com/en/p/-12332423/" and "999"
second loop should be:
"https://testing.com/en/p/-123456/" and "123"
and so on depending on whats inside the json basically.
So my question is how am I able to loop it so I can use those values for each loop?
As Adam Orlov pointed out in the coment, Object.entries() can be very useful here.
const URLobj = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
};
URLobj.URL.forEach(ob => {
console.log('ob', ob);
const entries = Object.entries(ob)[0]; // 0 just means the first key-value pair, but because each object has only one we can just use the first one
const url = entries[0];
const number = entries[1];
console.log('url', url);
console.log('number', number);
})
You mean something like this using Object.entries
const data = {
"URL": [
{"https://testing.com/en/p/-12332423/": "999"},
{"https://testing.com/en/p/-123456/": "123"},
{"https://testing.com/en/p/-456436346/": "422"}
]
}
data.URL.forEach(obj => { // loop
const [url, num] = Object.entries(obj)[0]; // grab the key and value from each entry - note the [0]
console.log("Url",url,"Number", num); // do something with them
})
let's call your object o1 for simplicity. So you can really go to town with this link - https://zellwk.com/blog/looping-through-js-objects/
or you can just use this code :
for(var i = 0; i < o1.URL.length; i++) {
//each entry
var site = Object.keys(URL[i]) [0];
var value = Object.values(URL[i]) [0];
// ... do whatever
}
don't forget each member of the array is an object (key : value) in its own right
You can extract the keys and their values into another object array using map
Then use the for loop on the newly created array. You can use this method on any object to separate their keys and values into another object array.
const data = {
"URL": [{
"https://testing.com/en/p/-12332423/": "999"
}, {
"https://testing.com/en/p/-123456/": "123"
},
{
"https://testing.com/en/p/-456436346/": "422"
}
]
}
var extracted = data.URL.map(e => ({
url: Object.keys(e)[0],
number: Object.values(e)[0]
}))
extracted.forEach((e) => console.log(e))
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);
}
So what i'm trying to achieve is creating a json flat file to store user info where i'm stuck is that i don't know how to add new nested objects that are empty and then save the json file and reload it.
what i have in my *json* file is this.
{
"users" : {
"test" : {
},
"test1" : {
}
}
}
I'm trying to add as many new objects as i want to it. So for example.
{
"users" : {
"test" : {
},
"test1" : {
},
"test2" : {
},
"test3" : {
}
}
}
My server side Javascript
json.users.push = username;
fs.writeFile("./storage.json", JSON.stringify(json, null, 4) , 'utf-8');
delete require.cache[require.resolve('./storage.json')];
json = require("./storage.json");
With this code it does not write the file so when the require is done i end up with the same file and my json object ends up like this when i console.log it
{
"users": {
"test": {},
"test1": {},
"push": "test2"
}
}
Please do not recommend some external module to solve something has simple as this. Also if any one can point me to a in depth json documentation that gets straight to the point with what i'm try to do it would be appreciated
Use [] to access a dynamic key on the object
json.users[username] = {a: 1, b: 2}
Be careful naming your variable like that tho because json the way you're using it is not JSON. JSON is a string, not an object with keys.
See the below demo for distinction
var json = '{"users":{"test1":{},"test2":{}}}';
var obj = JSON.parse(json);
var newuser = 'test3';
obj.users[newuser] = {};
console.log(JSON.stringify(obj));
//=> {"users":{"test1":{},"test2":{},"test3":{}}}