concatenate string to json object - javascript

I am trying to use mustache with a bootstrap calendar called Bic_Calendar
basically you can add events to the calendar with an object like this
var events = [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
},
]
;
what I want is using mustache to have a quick summary of the next events, the problem is that in order to mustache render the
template the object needs to be change to:
var events = {"events": [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
},
]}
;
so I am trying to concatenate the original event into a new one but it is not working, so i guess i am doing something wrong in the concatenation
var events1 = '{"events": '. concat(events) .concat('}');
var events1 = '{"events": ' + events + '}';
non of this options works!

var events is not JSON. It is a literal javascript array, you should not be concatenating it, but simply nesting it in a new object and then serializing into JSON if you need a JSON string.
var events = [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
},
];
var nestedEvents = { 'events': events };
var jsonEvents = JSON.stringify(nestedEvents);
As a general rule of thumb, if you find yourself tempted to manually build a JSON string, you are probably not taking the right approach. Build the data structure you want to serialize into JSON first, then serialize it.
The other takeaway, which seems to be a common point of confusion for developers, is that JSON is nothing more than a serialized string representation of some data structure. There is no such thing as a JSON object. The JSON format certainly bears a strong resemblance to a javascript object literal, but it is truly different and should be treated as such. In this case your events variable does not contain a JSON string, so you should not expect to be able to concatenate it as if it were a string.

You have an array of objects like
var events = [
{
date: "28/10/2013",
title: 'DUE DAY ENROLMENT',
},
{
date: "29/10/2013",
title: 'DUE DAY PAYMENT',
},
{
date: "31/10/2013",
title: '1st DAY OF CLASS',
}
];
Just make a new object with your event array like this
var eventsObj = { 'events': events };
If you need to make it a json string then you may use JSON.stringify, which will convert an object to json string. BTW, concat is array objects' method.

Related

How to reduce/concat objects based on some other value in javascript

I am wondering what js functions can be used in the following case to get some array values together.
Here I want to concatenate the description values if the date value is null.
var incomes = [ { date: '05/03', description: '1st Description on 05/03', amount: '399.49' },
{ date: null, description: '1st Description continued on 05/03', amount: null },
{ date: null, description: '1st Description continued on 05/03', amount: null },
{ date: '05/03', description: '2nd Description on 05/03', amount: '269.85' },
{ date: null, description: '2nd Description continued on 05/03', amount: null },
{ date: null, description: '2nd Description continued on 05/03', amount: null }];
The result should look like this:
var results = [ { date: '05/03',
description: '1st Description on 05/03, 1st Description continued on 05/03, 1st Description continued on 05/03',
amount: '399.49' },
{ date: '05/03',
description: '2nd Description on 05/03, 2nd Description continued on 05/03, 2nd Description continued on 05/03',
amount: '269.85' }];
I think that we can use the usual loops, conditions, etc. But are there any handy method to solve this?
This really isn't a good use case for reduce/concat types of operations. Reduce is supposed to be given a pure function that only relies on its parameters and doesn't mutate any values. You're trying to produce an array, which would either involve creating the array and then mutating it (adding values), or creating copies of the array (via concat), like this:
const results = incomes.reduce((agg, v) =>
v.date
? agg.concat([v])
: agg.slice(0, -1)
.concat([{
...agg.slice(-1)[0],
description: `${agg.slice(-1)[0].description}, ${v.description}`}]),
[])
As you can see, there's a lot of duplicative sliceing and concating going on here, which is wasteful from a performance perspective. Perhaps more importantly, it's hard to reason with and hard to debug. I'd probably stick with using a for loop that tracks state and pushes to an array instead.
let results = [];
for (let v of incomes) {
if (v.date) {
results.push({...v});
} else {
results[results.length - 1].description += ", " + v.description;
}
}

Unable to find item in this array when I do it outside of the map function it works inside it doens't

I am trying to make a calendar with events that are rendered dynamically.
I use this to create the days for the calendar and create an array to display. I try to create an events object containing the details for the events. When I try to outside of the initialDays map fuction it works fine and is able to find the object with the correct date and time however when I try to use find function inside of the initialDays map function I get this error.
events.find((item) => {
return item.datetime == dates
})
Uncaught (in promise) TypeError: Cannot read properties of undefined (reading 'length')
createDays()
{
this.today = startOfToday()
this.formatedDate = format(this.today, 'MMM, yyyy')
this.currentMonth = this.formatedDate
this.getNewDays = parse(this.currentMonth, 'MMM, yyyy', new Date())
this.firstDayCurrentMonth = parse(this.currentMonth, 'MMM, yyyy', new Date())
let initialDays = eachDayOfInterval({
start: startOfWeek(this.getNewDays, {weekStartsOn: 1}),
end: endOfWeek(endOfMonth(this.getNewDays), {weekStartsOn: 1})
})
let events = [{ id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-10', href: '#' }, { id: 4, name: 'Date night', time: '6PM', datetime: '2022-10-12', href: '#' }, { id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-13', href: '#' }]
events = events.map((events) => {
return {
id: events.id,
name: events.name,
time: events.time,
datetime: events.datetime,
href: events.href
}
})
const findevent = events.find((item) => {
return item.datetime === '2022-10-10'
})
console.log(findevent)
initialDays = initialDays.map((dates) => {
return {
date: format(dates, 'yyyy-MM-dd'),
isCurrentMonth: isSameMonth(this.getNewDays, dates),
isToday: isToday(dates),
isSelected: isSameDay(dates, this.today),
events: events.find((item) => {
return item.datetime == dates
})
}
})
this.days = initialDays
},
EDIT ***
InitialDays returns a array of dates from start of the current month to end of current month plus 1 week before and 1 week after.
I want the events to be filled in if they match dates. However currently it just fills every date with the all the events. I thought using the find method would work. Date-fns has a ```isSameDay`` function however it only returns true or false. Not sure how to continue...
{
"date": "2022-10-22",
"isCurrentMonth": true,
"isToday": false,
"isSelected": false,
"events": [
{
"id": 3,
"name": "Date night",
"time": "6PM",
"datetime": "2022-10-10",
"href": "#"
},
{
"id": 4,
"name": "Date night",
"time": "6PM",
"datetime": "2022-10-12",
"href": "#"
},
{
"id": 3,
"name": "Date night",
"time": "6PM",
"datetime": "2022-10-13",
"href": "#"
}
]
}
First, let's see the events you are working with:
let events = [{ id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-10', href: '#' }, { id: 4, name: 'Date night', time: '6PM', datetime: '2022-10-12', href: '#' }, { id: 3, name: 'Date night', time: '6PM', datetime: '2022-10-13', href: '#' }]
The items are objects and
const findevent = events.find((item) => {
return item.datetime === '2022-10-10'
})
is working for you, which proves that this is operational.
In the snippet below we can see that map does not work when you want to call it for an object
let initialDays = {
start: new Date(),
end: new Date()
};
initialDays = initialDays.map((dates) => {
return dates.length
})
therefore eachDayOfInterval returns an array (otherwise you would get an error, complaining that map is not a function). So, your function of eachDayOfInterval does something that you did not share, so it's unclear what this array will contain.
However, it is very safe to assume that the eachDayOfInterval returns an array of days (in whatever format). When you do something like
initialDays.map((dates) => {
//...
}
you therefore will iterate your dates and each iteration is a date (day). So the naming of dates above shows that you misunderstood this part and you assumed that you will have an array of dates inside the map callback, but you will have an individual date inside that callback instead, looping through the whole array.
The error suggests that you tried to read the property of length on undefined. This proves the following:
your dates has at least one undefined element, which is the technical reason you get this error
you treat the individual date as if it was an array of dates
items.map(item => something(item))
will loop items and perform a mapping for each item.

Convert user input string to an object to be accessed by function

I have data in the format (input):
doSomething({
type: 'type',
Unit: 'unit',
attributes: [
{
attribute: 'attribute',
value: form.first_name
},
{
attribute: 'attribute2',
value: form.family_name
}
],
groups: [
{
smth: 'string1',
smth2: 'string2',
start: timeStart.substring(0, 9)
}
]
})
I managed to take out the doSomething part with the parenthesis as to load the function from the corresponding module with
expression.split('({',1)[0]
However using the loaded function with the rest, obtained with:
expression.split(temp+'(')[1].trim().replace(/\n+/g, '').slice(0, -1)
does not work because it should be an object and not a string. Hardcoding the data in does work as it is automatically read as an object.
My question is if there is any way of converting the string that I get from the user and convert it to an object. I have tried to convert it to a json object with JSON.parse but I get an unexpected character t at position 3. Also I have tried new Object(myString) but that did not work either.
What I would like is to have the body of the provided function as an object as if I would hard code it, so that the function can evaluate the different fields properly.
Is there any way to easily achieve that?
EDIT: the "output" would be:
{
type: 'type',
Unit: 'unit',
attributes: [
{
attribute: 'attribute',
value: form.first_name
},
{
attribute: 'attribute2',
value: form.family_name
}
],
groups: [
{
smth: 'string1',
smth2: 'string2',
start: timeStart.substring(0, 9)
}
]
}
as an object. This is the critical part because I have this already but as a string. However the function that uses this, is expecting an object. Like previously mentioned, hard coding this would work, as it is read as an object, but I am getting the input mentioned above as a string from the user.
Aside: I know eval is evil. The user could do by this certain injections. This is only one possibility to do this there are certain other ways.
I just added before "output =", cut from the input-string the "doSomething(" and the last ")". By this I have a normal command-line which I could execute by eval.
I highly not recommend to use eval this way; especially you don't
know what the user will do, so you don't know what could all happen
with your code and data.
let form = {first_name: 'Mickey', family_name: 'Mouse'};
let timeStart = (new Date()).toString();
let input = `doSomething({
type: 'type',
Unit: 'unit',
attributes: [
{
attribute: 'attribute',
value: form.first_name
},
{
attribute: 'attribute2',
value: form.family_name
}
],
groups: [
{
smth: 'string1',
smth2: 'string2',
start: timeStart.substring(0, 9)
}
]
})`;
let pos= "doSomething(".length;
input = 'output = ' + input.substr(pos, input.length-pos-1);
eval(input);
console.log(output);

How to convert stringified surveyjs JSON-like object into actual JSON

I'm working on a an application that uses the survey building library surveyjs. I'm building a tool where users can input a survey JSON from that website into a form that is then sent as a string via an ajax request that triggers an AWS Lambda function. The lambda function takes the ajax request and inserts their survey into a MongoDB instance using mongoose.
When the string comes into the lambda function, it looks like this:
"{ pages: [ { name: 'page1', elements: [ { type: 'radiogroup', name: 'question1', title: 'IS THIS A SURVEY?', choices: [ { value: 'item1', text: 'Yes' }, { value: 'item2', text: 'No' } ] } ] } ]}"
And when I try to parse that string, I get this error:
Error: JSON Parse error: Expected '}'
I think it might have something to do with the JSON keys not being strings. I've also read that my use of single quotes could potentially be the problem, but I've exhausted my knowledge base.
Overall, my question is: How can I convert that string into a JSON object?
Thanks!
JSON strings need their string properties and values to be double-quoted. Use a regular expression and replace:
const originalStr = "{ pages: [ { name: 'page1', elements: [ { type: 'radiogroup', name: 'question1', title: 'IS THIS A SURVEY?', choices: [ { value: 'item1', text: 'Yes' }, { value: 'item2', text: 'No' } ] } ] } ]}";
const finalStr = originalStr
.replace(/'/g, '"')
.replace(/(\w+):/g, '"$1":');
console.log(JSON.parse(finalStr).pages);
That said, it would be better to fix whatever's serving the results in the first place, if at all possible.
If your lambda function is written using javascript then you can make use of eval to parse malformed JSON, however the eval'd string is evaluated as actual javascript within the current context so to get the result you have to set a variable within the string. Example:
var malformedJsonString = "{unquotedName: 'single quoted value'}";
eval("var myParsedJsonObject = "+malformedJsonString+";");
// myParsedJsonObject now contains your parsed JSON object

How to access a specific index of an array in node.js

I want to get only the AID from the solution now i am getting. I tried rows[0] but was not successful.
Code:
console.log('The solution is: ', rows);
Output:
The solution is:
[ { AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89 } ]
Use rows[0]["AID"] to access the AID property.
Let's understand your overall data structure here:
var rows = [
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
];
The variable rows is an array of objects. Thus rows[n] gets you a specified object in that array and therefore rows[0] is the first object in the array which would be:
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
So, now you want to access the AID property in that object so you can just do:
rows[0].AID
And, here's a working snippet demo:
var rows = [
{
AID: 6520,
DID: 113071,
TITLE: 'First Knight',
DATE: '7/7/1995',
SCORE: 89
}
];
document.write(rows[0].AID);

Categories

Resources