parsing error JSON.parse(unexpected token u) - javascript

var storage = chrome.storage.local;
var cachedStorage = {};
this is js file.It shows unexpected token u.even though I've done parsing correctly.and it also shows unexpected token for for its html source page.can any one suggest me how to sort this out.
var defaultStorage = [{
savedPatterns: JSON.stringify([
[{
"en": "English"
}, {
"it": "Italian"
}, "25", true],
[{
"en": "English"
}, {
"la": "Latin"
}, "15", false]
]),
}];
error occurs here unexpected token u
function createPattern() {
console.log('createPattern begin');
var patterns = JSON.parse(S('savedPatterns'));
var srce = [],
trg = [],
prb = [];
console.log(S('savedPatterns'));
console.debug(S('savedPatterns'));
var translator = document.getElementById('translatorService');
var service = translator.children[translator.selectedIndex].value;
srce[0] = document.getElementById('sourceLanguage');
srce[1] = srce[0].children[srce[0].selectedIndex].value;
srce[2] = srce[0].children[srce[0].selectedIndex].text;
trg[0] = document.getElementById('targetLanguage');
trg[1] = trg[0].children[trg[0].selectedIndex].value;
trg[2] = trg[0].children[trg[0].selectedIndex].text;
prb[0] = document.getElementById('translationProbability');
prb[1] = prb[0].children[prb[0].selectedIndex].value;
patterns.push([
[srce[1], srce[2]],
[trg[1], trg[2]],
prb[1],
false,
service
]);
saveBulk({
'savedPatterns': JSON.stringify(patterns)
}, 'Saved Pattern');
console.log('createPattern end');
}
function S(key) {
return cachedStorage[key];
}
function loadStorageAndUpdate(callback) {
storage.get(null, function(data) {
console.log('data: ' + data + ' : ' + JSON.stringify(data));
var d = {};
if (!data || JSON.stringify(data) == '{}') { // in this case, storage was not initialized yet
console.log('setting storage to defaultStorage (stringified): ');
console.log(JSON.stringify(defaultStorage));
storage.set(defaultStorage);
d = defaultStorage;
} else {
d = data;
}
cachedStorage = d;
if (!!callback) {
callback(d);
}
});
}

Error Unexpected token comes when JSON.parse fails and depending on character (u in this case), you can assume its cause.
u is if value is undefined
o is if value is object
try {
JSON.parse(undefined)
} catch (ex) {
document.write(ex.message + "<br/>")
}
try {
JSON.parse({})
} catch (ex) {
document.write(ex.message)
}
You can try something like this:
function s(key) {
var obj = {
foo: "foo",
bar: "bar"
}
var v = null;
try {
v = JSON.parse(obj[key]);
} catch () {
v = obj[key];
}
return v;
}
function main() {
var v = s("foo");
}
Please refer following post for more information. Uncaught SyntaxError: Unexpected token with JSON.parse

You're trying to parse undefined. When you call JSON.parse(), you're passing in S('savedPatterns'), which in turn tries to access cachedStorage['savedPatterns'], but that starts as undefined, which you can't parse. You could just initialize your cachedStorage as:
var cachedStorage = {
savedPatterns: JSON.stringify([])
};

Related

WKWebView evaluateJavaScript returns wrong JavaScript Object

I'm making a hybrid app and using WKWebView.
I need to pass a JavaScript Object to the emitter command to open the edit dialog.
Here is my code:
let statDict: [String: Any] = [
"income" : account.stat.income,
"expense" : account.stat.expense,
"summary" : account.stat.summary,
"incomeShorten" : account.stat.incomeShorten,
"expenseShorten" : account.stat.expenseShorten,
"summaryShorten": account.stat.summaryShorten
]
let accountDict: [String: Any] = [
"id": account.id,
"name": account.name,
"description": "",
"icon": account.icon,
"currency": account.currency,
"customer_contact_id": account.customer_contact_id ?? 0,
"is_archived": account.is_archived,
"sort": account.sort,
"create_datetime": account.create_datetime,
"update_datetime": account.update_datetime ?? "",
"stat": statDict
]
let accountData = try! JSONSerialization.data(withJSONObject: accountDict, options: JSONSerialization.WritingOptions(rawValue: 0))
guard let accountString = String(data: accountData, encoding: .utf8) else {
return
}
webView.evaluateJavaScript("function parse(string){ return JSON.parse(string)}") { result, error in
if error == nil { // this is returns correct staff
}
}
webView.evaluateJavaScript("parse('\(accountString)')") { object, error in
if error == nil {
let object = object as AnyObject
print("parse object \(object)")
webView.evaluateJavaScript("window.emitter.emit('openDialog', 'Account', \(object))") { (result, error) in
if error == nil { // here the error "Unexpected token '='..."
webView.evaluateJavaScript("window.emitter.on('closeDialog', function(){ window.webkit.messageHandlers.emitterMessage.postMessage('closeDialog'); })") { (result, error) in
if error == nil {
}
}
webView.evaluateJavaScript("window.emitter.on('createAccount', function(){ window.webkit.messageHandlers.emitterMessage.postMessage('createAccount'); })") { (result, error) in
if error == nil {
}
}
} else {
print(error as Any)
}
}
}
}
The \ (object) returned by the function looks like this:
{
"create_datetime" = "2021-08-24 19:19:28";
currency = RUB;
"customer_contact_id" = 1;
description = "";
icon = "";
id = 7;
"is_archived" = 0;
name = "Business 111";
sort = 0;
stat = {
expense = 0;
expenseShorten = 0;
income = 300000;
incomeShorten = 300K;
summary = 300000;
summaryShorten = 300K;
};
"update_datetime" = "";
}
but it should look like this:
{
create_datetime: "2021-08-24 19:19:28",
currency: "RUB",
customer_contact_id: 1,
description: "",
icon: "",
id: 7,
is_archived: false,
name: "Business 111",
sort: 0,
stat: {
expense: 0,
expenseShorten: "0",
income: 300000,
incomeShorten: "300K",
summary: 300000,
summaryShorten: "300K"
},
update_datetime: ""
}
With such an object, the compiler generates the error Unexpected token '='. Expected an identifier as property name.
The parse (string) function will return the correct object if you run it in the js compiler, but in swift the output is not correct.
How to bring an object to the correct form?
You are trying to pass the string interpolated representation of a Swift object (NSMutableDictionary in your case) to Javascript.
Instead you can directly pass the JSON representation to JS context since JSON is a native Javascript object it should do what you are trying to achieve :
/// Sample emitter function that consumes object an prints its local parameter, also assigns it to sample object value in window.
self.webView?.evaluateJavaScript(
"window.emitter = (sampleObject) => { window.sampleObject = sampleObject;setTimeout(function(){console.log('Hello sampleObject : ',sampleObject.name); }, 7000);}"
) { result, error in
if error == nil { // this is returns correct staff
}
}
self.webView?.evaluateJavaScript("window.emitter(\(accountString));") { result, error in
if error == nil {
print("parse object \(result)")
}
}
Result in window :

Writing javascript function in a better way

function returnsSomething(data1, data2) {
let error = null;
let something = {
varA = data1 ? data1 : error += 'varA';
varB = data2 ? data2 : error += 'varB';
}
return {
status: error ? false : true;
returnedData: error ? error += 'not available' : something
}
}
function callsThePreviousFunction() {
let data1 = {
a: something1,
b: something2
}
let data2 = {
a: something3,
b: something4
}
let storeData = returnsSomething(data1, data2)
if(storeData.status){
return storeData.returnedData;
}else{
return false
}
}
I believe the function returnsSomething can be written in a better way to return the data and return the stored errors based on the conditions. Any help will be highly appreciated. THANK YOU

How to remove double quotes from an array of strings

Say I have the array below
var someStuff = [
"start", { one: "one"},
"setSomething", "foobar",
"someBool", true
];
How can I transform it to be as below
var someStuff = [
MainFunc.start({one: "one"}),
MainFunc.setClientId('foobar'),
MainFunc.someBool(true)
];
Assuming you want an array containing results from a number of function calls, this is how you can get that. You need to iterate over the array, get each function from the MainFunc object and then call that each time.
I included handling for a non-existing function being called, which happened to be in your example (perhaps not intentional).
var MainFunc = {
start : function(x) { return "start called with " + x.toString(); },
setClientId : function(x) { return "setClientId called with " + x.toString(); },
someBool : function(x) { return "someBool called with " + x.toString(); }
}
var someStuff = [
"start", { one: "one" },
"setSomething", "foobar",
"setClientId", "foobar",
"someBool", true
];
var result = Process(someStuff);
function Process(arr) {
var result = [];
for (var i = 0; i < arr.length; i += 2) {
let fnToCall = MainFunc[arr[i]];
let fnResult = fnToCall ? fnToCall(arr[i + 1]) : "(unknown: '" + arr[i] + "')";
result.push(fnResult);
}
return result;
}
console.log(result);
Try it like this (You need to use arrow functions because otherwise the function would get called straigh away):
var someStuff = [
"start", { one: "one"},
"setSomething", "foobar",
"someBool", true
];
let output = []
for(let i=0, j=0; i<someStuff.length; i+=2, j++) {
let functionName = someStuff[i];
let functionArgs = someStuff[i+1];
output[j] = () => MainFunc[functionName](functionArgs);
}
console.log(output);
I think you might want to do this
function mainFunc() {
this.start = function(obj) { console.log("start",obj) };
this.setSomething = function(obj) { console.log("set",obj) };
this.someBool = function(obj) { console.log("bool",obj) };
}
var someStuff = {
"start": { "one":"one"},
"setSomething": "foobar",
"someBool": true
};
var mf = new mainFunc();
for (var a in someStuff) {
mf[a](someStuff[a])
}
For better readability, define an array of objects with action and its parameter.
const mainFunc = {
start: (param) => console.log('start', param),
setSomething: (param) => console.log('SetSomething', param),
someBool: (param) => console.log('someBool', param)
}
var someStuff = [
{ action: "start", param: { one: "one"} },
{ action: "setSomething", param: "foobar" },
{ action: "someBool", param: true }
];
someStuff.forEach(stuff => {
if (typeof mainFunc[stuff.action] === 'function') {
mainFunc[stuff.action](stuff.param);
}
});

Ditto.asByteBuffer(bytePayload) throws exception

In the eclipse-ditto mappingcontext I placed following incomingScript:
function mapToDittoProtocolMsg(headers, textPayload, bytePayload, contentType) {
switch (contentType) {
case "application/json":
var jsonData = JSON.parse(textPayload);
var temperature = jsonData.temp;
var humidity = jsonData.hum;
var path;
var value;
if (temperature != null && humidity != null) {
path = "/features";
value = {
temperature: {
properties: {
value: temperature
}
},
humidity: {
properties: {
value: humidity
}
}
};
} else if (temperature != null) {
path = "/features/temperature/properties/value";
value = temperature;
} else if (humidity != null) {
path = "/features/humidity/properties/value";
value = humidity;
}
if (!path || !value) {
return null;
}
return Ditto.buildDittoProtocolMsg("tenant_aloxy", headers["device_id"], "things", "twin", "commands", "modify", path, headers, value);
break;
case "application/octet-stream":
let byteBuf = Ditto.asByteBuffer(bytePayload);
var path = "/features/alp/properties/value";
var value = 21;
return Ditto.buildDittoProtocolMsg("tenant_aloxy", headers["device_id"], "things", "twin", "commands", "modify", path, headers, value);
default:
return null;
}
}
When I send in binary data, I'm hitting the second case of the switch as expected. However, when it tries to convert the incoming data as a bytebuffer (Ditto.asByteBuffer(bytePayload);) it throws following exception:
ReferenceError: "dcodeIO" is not defined.
That helper function in the "Ditto" scope requires the "ByteBuffer.js" library as described in the documentation: https://www.eclipse.org/ditto/connectivity-mapping.html#bytebufferjs (dcodeIO was used as scope for that library).
That means you have simply to enable that this library is loaded in the configuration of your mapping: https://www.eclipse.org/ditto/connectivity-mapping.html#configuration-options
{
"incomingScript": "...",
"outgoingScript": "...",
"loadBytebufferJS": true,
"loadLongJS": true
}
After that you should be able to use Ditto.asByteBuffer()

How to check if boolean is passed as string?

So in below code if i pass ancillaryProductInd as boolean code works, but when I pass it as a string, it does not work. In my understanding the below code should only work when I pass "false" string value and throw error on boolean. Any idea what is the issue here ?
main.ts
request
var rxInfos = [{
"ancillaryProductInd": "false",
"indexID": "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}]
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach((rxInfo) => {
const subQuestion = {
question: []
};
if (rxInfo.ancillaryProductInd !== undefined && rxInfo.ancillaryProductInd === "false") {
subQuestion.question = data;
subQuestionArray.push(subQuestion);
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [{
some data
}]);
Your example code works as expected with a string value "false" and doesnt run the if block when a boolean is used. See my example:
var rxInfos = [
{
ancillaryProductInd: "false",
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
},
{
ancillaryProductInd: false,
indexID: "eyJrZXkiOiIEOHdpNUpNWmR3PT0ifQ=="
}
];
function subQuestionsHandler(rxInfos, data) {
const subQuestionArray = [];
rxInfos.forEach(rxInfo => {
const subQuestion = {
question: []
};
if (
rxInfo.ancillaryProductInd !== undefined &&
rxInfo.ancillaryProductInd === "false"
) {
console.log("no error");
subQuestion.question = data;
subQuestionArray.push(subQuestion);
} else {
console.log("throw error");
}
});
return subQuestionArray;
}
subQuestionsHandler(rxInfos, [
{
test: ""
}
]);

Categories