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

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

Related

Why is my JSON object showing [Array] instead of the data in javascript after reformatting?

Currently I am trying to create a JSON object in java script which has an additional array containing all of the data that I currently posses:
src is a JSON object which before any code is run is equal to:
[
{
_id: new ObjectId("629ac43586b27bfd70337d06"),
Title: 'Test Poll',
Option: [ 'Test Option 1', 'Test Option 2', 'Test Option 3' ]
},
{
_id: new ObjectId("629afc9286b27bfd70337d09"),
Title: 'Test Poll 2',
Option: [ 'Test Option 1' ]
}
]
I need to reformat this object so that it is contained within a separate array which I am currently attempting to do with this line:
var context = { poll:src };
This results in a reformatting of the JSON object which I do not understand, after running this code context contains:
poll: [
{
_id: new ObjectId("629ac43586b27bfd70337d06"),
Title: 'Test Poll',
Option: [Array]
},
{
_id: new ObjectId("629afc9286b27bfd70337d09"),
Title: 'Test Poll 2',
Option: [Array]
}
]
It gets rid of the Option arrays and replaces them with [Array]. I need to keep these arrays and I am not sure what to change to fix this as I have tried looking elsewhere for answers. Does anyone have an idea of what is going on here?
Ok they are arrays I am just too new to realize that it would not print fully. I was attempting to use handlebars on these Option arrays to print the list and I was forgetting to use the implicit this for the variable name instead of just 'Option'.
Problem solved.

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);

Convert String to an Array in JS

In my project I have a use case like the below:
I have a response Array like below,
(4) [{…}, {…}, {…}, {…}]
0:{header: 0, name: "Name", field: "Id"}
1:{header: 3, name: "LastName", field: "Agreement__c"}
2:{header: 3, name: "LastName", field: "Amount__c"}
3:{header: 3, name: "LastName", field: "BIC__c"}
length:4
from the above I convert the above array to String by using,
JSON.stringify(responseArray) and store it in a string field.
After that I want to do some manipulation dynamically to that value of that field. So when I get the value back from the field it came as like below,
[{"header":0,"name":"Name","field":"Id"},
{"header":3,"name":"LastName","field":"Agreement__c"},
{"header":3,"name":"LastName","field":"Amount__c"},
{"header":3,"name":"LastName","field":"BIC__c"}]
Anyone please help me to convert the above string response to an Array in Javascript like as follows,
index 0 -> {"header":0,"name":"Name","field":"Id"}
index 1 -> {"header":3,"name":"LastName","field":"Agreement"}
I have tried with the split function but couldn't able to achieve the exact need.
Put square brackets at the beginning and end of your string and call JSON.parse:
$ node
> const text = `{"header":0,"name":"Name","field":"Id"},
{"header":3,"name":"LastName","field":"Agreement"},
{"header":3,"name":"LastName","field":"Amount"},
{"header":3,"name":"LastName","field":"BIC"}`
> JSON.parse(`[${text}]`)
[ { header: 0, name: 'Name', field: 'Id' },
{ header: 3, name: 'LastName', field: 'Agreement' },
{ header: 3, name: 'LastName', field: 'Amount' },
{ header: 3, name: 'LastName', field: 'BIC' } ]
you can use following code sample first append "[" at begging of your string and "]" at end of your string so your string will be well formatted as JSON array then it is so easy to parse it using JSON.parse built in function
a = '['+'{"header":0,"name":"Name","field":"Id"}, {"header":3,"name":"LastName","field":"Agreement"}, {"header":3,"name":"LastName","field":"Amount"}, {"header":3,"name":"LastName","field":"BIC"}'+"]"
var myarray = JSON.parse(a);
yes, JSON.parse is the real easy answer for this.
You just need some basic string manipulations, By the way, I changed your string into a valid syntax
var str="{\"header\":0,\"name\":\"Name\",\"field\":\"Id\"},{\"header\":3,\"name\":\"LastName\",\"field\":\"Agreement\"},{\"header\":3,\"name\":\"LastName\",\"field\":\"Amount\"},{\"header\":3,\"name\":\"LastName\",\"field\":\"BIC\"}";
str=str.replace(/},{/g,"}|{");
var arr = str.split("|");
var json = [];
for(i=0; i<arr.length; i++){
json.push(JSON.parse(arr[i]));
}
//console.log(json);
console.log(json[0]);
console.log(json[1]);
try this
var textstr = '[{"header":0,"name":"Name","field":"Id"},{"header":3,"name":"LastName","field":"Agreement"}, {"header":3,"name":"LastName","field":"Amount"}, {"header":3,"name":"LastName","field":"BIC"}]';
var textstr2 = JSON.parse(textstr);
console.log(textstr2)

Serialize a strange js object

I got a js object, if I use the console.log, the result is like this:
{ title: 'testCase',
id: '5e41538bbf4a7e93a12925a3e6ca12',
links:
[ URLLink {
link: 'www.google.com' } ]
}
but If I use console.log("sometext" + wireObj);
The result is :
sometext[object Object]
If I use JSON.stringify(), the result will become:
{ title: 'testCase',
id: '5e41538bbf4a7e93a12925a3e6ca12',
links:
[{
link: 'www.google.com' }]
}
As you can see, the URLLink is missing, I would like to preserve this information as well. Any comments?
If what you're trying to do is model links as an array of URLLink objects then maybe you could do it like this:
{ title: 'testCase',
id: '5e41538bbf4a7e93a12925a3e6ca12',
links:
[ {URLLink: {link: 'www.google.com' }},
{URLLink: {link: 'www.yahoo.com' }} ]
}
Note the curly braces wrapping URLLink and the colon mentioned by #alexandru-ionut-mihai
That would be parsed like below:

JSON $ref and accessing it

Assume I have the following JSON structure.
data = {
questions: [
{color:
{name: 'What is your fav color?',
type: 'input'
}
},
{...more question like this...}
],
layouts: [
{row_1:
{format: '...', $ref: '#/questions/color', id: 1}
},
{...more format like this...}
]
}
Using Javascript, is it possible to "expand" the $ref from '#/questions/color' to the actual object defined in this JSON? Or do I have to write a custom function to traverse through the JSON?
Clarification:
If I were to do data.layouts[0]["row_1"]["$ref"] wouldn't the result be #/questions/colorWhere I want it to be the actual object that it references. ie)
{name: 'What is your fav color?',
type: 'input'
}
Basically I need some way to do: foo(data, '#/questions/color') => the data that it is pointing to.
Thanks

Categories

Resources