I'm receiving a string like obj{a="foo",b="bar",c=3,d=4.0} inside a nodejs environment I'm working in and I'm trying to convert this String into a reference-able Object like this:
{
a : "foo",
b : "bar",
c : 3,
d : 4.0
}
Assigned to obj of course.
I've used a myriad of formatting tricks but whenever I call JSON.parse() I get unexpected character errors. Usually on the first alpha-character it sees.
My next step is to write several nested loops to make all of the assignments manually but I'm hoping someone can point me in the right direction on how to parse this.
EDIT: Ok there's a little more to the story and I thought I should omit it but I guess explaining everything would be helpful.
The actual data packet that I'm receiving looks like this.
ack{a="000000061",b=0,c=2.0}\rb{a=244.0,b=255,c=4.0}\rc{a=6.0,b=55,c=55}endack;
So yeah that's the actual string I'm trying to parse into three distinct accessible Objects. I know I'm having a brain fart from a long day but yeah it's giving me a run for my money right now.
First replace the "=" with ":" and remove the obj infront
str = str.replace(/=/g, ":").replace("obj{", "{")
Since it's not in correct json format (but can be read by js parser) we can't use JSON.parse but we can use eval
eval("var obj = " + str);
Obvious there are some assumptions with this technique such that = always mean colon and you won't have obj{ as text (but the latter can be fixed with a simple substring method)
Keep in mind eval is also considered evil so use at your own risk. Imagine if the user were to send bad data, they could easily get into your parser and run something malicious. But hopefully this will give you an idea or inspiration to a better solution.
You can go a step further and use
str = 'obj{a="foo",b="bar",c=3,d=4.0}'
str = str.substr(3,str.length).replace(/([{,])([\w])=/g, '$1\"$2\":');
var obj = JSON.parse(str);
Related
I cant use send_Keys() method to input values in the current website im working on.
So im trying to use javascript to input values.
i tried click() and clear() together with send_keys() before i decided to use javascript but to my disappointment, it didnt work.
i use the javascript code to input value below
driver.execute_script("document.getElementById('CustCd').setAttribute('value', 'J590')")
and it worked.
But currently my code is inside a loop and the value changes, how can i replace J590 with a variable that gets the value?
Here is the code that i tried
ccr_No = XLUtlis.readData(path, 'ccr', r, 1)
driver.execute_script("document.getElementById('CCRNo').value=ccr_No")
I know its wrong, any help would be appreciated. My Javascript is weak.
Just some side note if anybody would be able to solve my send_keys() error.
The function only takes in the first character that i send. For example, send_keys("J590") gives J, send_keys("J590-TE21") gives J-
First, the correct way to set the current value of an input is to assign to the value property. There is no attribute for the inputs current value (the value attribute is the input's default value, more here).
The rest is a special case of a general-purpose question: "How do I output a Python variable's value into JavaScript code?"
If the string you're outputting doesn't contain quotes or backslashes, you may get away with using a format string and outputting the value in quotes as Guy shows. (JavaScript has two kinds of quotes, ' and "; you only need to escape the kind you use around the value.) Those kinds of assumptions tend to break down, though; as soon as the string is Hi, I'm Joe that approach breaks.
In the general case, to ensure proper escaping and that all values are written correctly, you can use JSON:
import json
value = 'J590'
driver.execute_script(f"document.getElementById('CustCd').value = {json.dumps(value)};")
That outputs:
document.getElementById('CustCd').value = "J590";
Live Example
That way, you don't have to worry about quoting and escaping, it's all handled for you since valid JSON is valid JavaScript (thanks to a recent JavaScript specification fix; prior to that there was an edge case incompatibility that people almost never ran into).
It's also useful for numbers, or more complex things you might want to pass to hte JavaScript code. For instance:
import json
class Example:
foo = ""
bar = 0
def __init__(self, foo, bar):
self.foo = foo
self.bar = bar
value = Example("I'm a string with \"quotes\" in it.", 42)
print(f"const obj = {json.dumps(value.__dict__)};")
num = 42
print(f"const num = {json.dumps(num)};")
That outputs:
const obj = {"foo": "I'm a string with \"quotes\" in it.", "bar": 42};
const num = 42;
obj ends up being an object, because the initializer is a valid JavaScript object literal containing the data from the Example object. Similarly, num is a valid JavaScript number.
Live Example
You need to insert the variable as variable, not literal
value = 'J590'
driver.execute_script(f"document.getElementById('CustCd').setAttribute('value', '{value}')")
Using Javascript to input the values of a variable you can use the following solution:
ccr_No = XLUtlis.readData(path, 'ccr', r, 1)
# ccr_No = J590
driver.execute_script("document.getElementById('CCRNo').value='" + ccr_No + "';")
An example, to input the values of a variable within Search Box of Google Home Page:
Code Block:
driver.get("https://www.google.com/")
value = 'J590'
driver.execute_script("document.getElementsByName('q')[0].value='" + value + "';")
Browser Snapshot:
You can find a relevant discussion in Selenium : How to send variable character strings through executeScript()
Short description:
Is there a javascript JSON-converter out there that is able to preserve Dates and does not use eval?
Example:
var obj1 = { someInt: 1, someDate: new Date(1388361600000) };
var obj2 = parseJSON(toJSON(obj1));
//obj2.someDate should now be of type Date and not String
//(like in ordinary json-parsers).
Long description:
I think most people working with JSON already had the problem of how to transmit a Date:
var obj = { someInt: 1, someDate: new Date(1388361600000) }
When converting this to JSON and back, the date suddenly became a String:
JSON.parse(JSON.stringify(obj))
== { someInt: 1, someDate: "2013-12-30T00:00:00.000Z" }
This is a huge disadvantage since you cannot easily submit a Date using JSON. There is always some post-processing necessary (and you need to know where to look for the dates).
Then Microsoft found a loophole in the specification of JSON and - by convention - encodes a date as follows:
{"someInt":1,"someDate":"\/Date(1388361600000)\/"}
The brilliance in this is that there is a now a definitive way to tell a String from a Date inside a valid JSON-string: An encoded String will never contain the substring #"/" (a backslash followed by a slash, not to be confused with an escaped slash). Thus a parser that knows this convention can now safely create the Date-object.
If a parser does not know this convention, the date will just be parsed to the harmless and readable String "/Date(1388361600000)/".
The huge drawback is that there seems to be no parser that can read this without using eval. Microsoft proposes the following way to read this:
var obj = eval("(" + s.replace(/\"\\\/Date\((\d+)\)\\\/\"/g, function (match, time) { return "new Date(" + time + ")"; }) + ")");
This works like a charm: You never have to care about Dates in JSON anymore. But it uses the very unsafe eval-method.
Do you know any ready-to-use-parser that achieves the same result without using eval?
EDIT
There was some confusion in the comments about the advantages of the tweaked encoding.
I set up a jsFiddle that should make the intentions clear: http://jsfiddle.net/AJheH/
I disagree with adeno's comment that JSON is a notation for strings and cannot represent objects. Json is a notation for compound data types which must be in the form of a serialized objects, albeit that the primitive types can only be integer, float, string or bool. (update: if you've ever had deal with spaghetti coded XML, then you'll appreciate that maybe this is a good thing too!)
Presumably hungarian notation has lost favour with Microsoft if they now think that creating a non-standard notation incorporating the data type to describe a type is better idea.
Of itself 'eval' is not evil - it makes solving some problems a lot easier - but it's very difficult to implement good security while using it. Indeed it's disabled by default with a Content Security Policy.
IMHO it boils down to storing the date as 1388361600000 or "2013-12-30T00:00:00.000Z". IMHO the latter has significantly more semantic value - taken out of context it is clearly a date+time while the latter could be just about anything. Both can be parsed by the ECMAscript Date object without resorting to using eval. Yes this does require code to process the data - but what can you do with an sort of data without parsing it? he only time I can see this as being an advanage is with a schemaless database - but in fairness this is a BIG problem.
The issue is the following line of code, here is an example function and take a look at parseWithDate function, add the script to the page and change the following line to this it will work.
http://www.asp.net/ajaxlibrary/jquery_webforms_serialize_dates_to_json.ashx
var parsed1 = JSON.parse(s1); // changed to below
var parsed1 = JSON.parseWithDate(s1);
Updated jsFiddle that works http://jsfiddle.net/GLb67/1/
I have a site and I used AJAX. And I got some problems.
Server return JSON string something like this {a:"x48\x65\x6C\x6C\x6F"}.
Then in xx.responseText, we have this string '{a:"\x48\x65\x6C\x6C\x6F"}'.
But if I create JavaScript string "\x48\x65\x6C\x6C\x6F" then I have "Hello" and not HEX!
Is it possible get in xx.responseText "real" text from HEX (automatically, without .replace())?
If the output is at all regular (predictable), .replace() is probably the simplest.
var escapeSequences = xx.responseText.replace(/^\{a:/, '').replace(/\}$/, '');
console.log(escapeSequences === "\"\\x48\\x65\\x6C\\x6C\\x6F\""); // true
Or, if a string literal that's equivalent in value but may not otherwise be the same is sufficient, you could parse (see below) and then stringify() an individual property.
console.log(JSON.stringify(data.a) === "\"Hello\""); // true
Otherwise, you'll likely need to run responseText through a lexer to tokenize it and retrieve the literal from that. JavaScript doesn't include an option for this separate from parsing/evaluating, so you'll need to find a library for this.
"Lexer written in JavaScript?" may be a good place to start for that.
To parse it:
Since it appears to be a string of code, you'll likely have to use eval().
var data = eval('(' + xx.responseText + ')');
console.log(data.a); // Hello
Note: The parenthesis make sure {...} is evaluated as an Object literal rather than as a block.
Also, I'd suggest looking into alternatives to code for communicating data like this.
A common option is JSON, which takes its syntax from JavaScript, but uses a rather strict subset. It doesn't allow functions or other potentially problematic code to be included.
var data = JSON.parse(xx.responseText);
console.log(data.a); // Hello
Visiting JSON.org, you should be able to find a reference or library for the choice of server-side language to output JSON.
{ "a": "Hello" }
Why not just let the JSON parser do its job and handle the \x escape sequences, and then just convert the string back to hex again afterwards, e.g.
function charToHex(c) {
var hex = c.charCodeAt(0).toString(16);
return (hex.length === 2) ? hex : '0' + hex;
}
"Hello".replace(/./g, charToHex); // gives "48656c6c6f"
I am being sent an ill formed JSON string from a third party. I tried using JSON.parse(str) to parse it into a JavaScript object but it of course failed.
The reason being is that the keys are not strings:
{min: 100}
As opposed to valid JSON string (which parses just fine):
{"min": 100}
I need to accept the ill formed string for now. I imagine forgetting to properly quote keys is a common mistake. Is there a good way to change this to a valid JSON string so that I can parse it? For now I may have to parse character by character and try and form an object, which sounds awful.
Ideas?
You could just eval, but that would be bad security practice if you don't trust the source. Better solution would be to either modify the string manually to quote the keys or use a tool someone else has written that does this for you (check out https://github.com/daepark/JSOL written by daepark).
I did this just recently, using Uglifyjs to evaluate:
var jsp = require("uglify-js").parser;
var pro = require("uglify-js").uglify;
var orig_code = "var myobject = " + badJSONobject;
var ast = jsp.parse(orig_code); // parse code and get the initial AST
var final_code = pro.gen_code(ast); // regenerate code
$('head').append('<script>' + final_code + '; console.log(JSON.stringify(myobject));</script>');
This is really sloppy in a way, and has all the same problems as an eval() based solution, but if you just need to parse/reformat the data one time, then the above should get you a clean JSON copy of the JS object.
Depending on what else is in the JSON, you could simply do a string replace and replace '{' with '{"' and ':' with '":'.
I have a variable called "result",
var result;
that result value is equal to following value, please presume that is just a string :)
---------result value -----------
for (;;);{
"send":1,
"payload":{
"config":{
"website":"",
"title":"welcome to site",
"website-module":1313508674538,
"manufatureid":"id.249530475080015",
"tableid":"id.272772962740259",
"adminid":100002741928612,
"offline":null,
"adminemail":"admin#website.com",
"adminame":"George",
"tags":"web:design:template",
"source":"source:design:web",
"sitelog":[],
"errorlog":0,
"RespondActionlog":0,
"map":null
},
"imgupload":""
},
"criticalerror":[0],
"report":true
}
---------result value------------
From that value, I would like to extract tableid which is "id.272772962740259" with classic Javascript.
How can I extract the code, please let me know how can i do with simple javascript, please don't use Jquery, all I just need is simple javascript.
You can simply evaluate the value of the variable to obtain the values. However, please note that your current value is not valid JSON; that for(;;); at the beginning of the value invalidates the format. Remove that, and you can do this:
var object = eval('(' + resultMinusThatForLoop + ')');
alert(object.payload.config.tableid);
If that data is a string the parse it with a JSON parse. The following should get the value you want
JSON.parse(result).payload.config.tableid; // "id.272772962740259"
Edit: though, as Tejs says, the for(;;) invalidates the string and stops it from being parsed. If you can remove that, do.
You need to remove the empty for loop, then parse the string. DO NOT use eval; most modern browsers provide built-in JSON-parsing facilities, but you can use json2.js if yours does not. Assuming that you assign the results of parsing the JSON to result, you should be able to get that value using result.payload.config.tableid.
You should probably read a good JS reference. JavaScript: The Good Parts or Eloquent JavaScript would be a good choice.
If result is a javascript object and not a string, you can just use 'result.payload.config.tableid'.
If it is not, how do you get the AJAX result? Are you using XmlHttpRequest directly? Most libraries will give you a javascript object, you might be missing a flag or not sending the response back with the right content type.
If it is a string and you want to parse it manually, you should use a JSON parser. Newer browsers have one built in as window.JSON, but there is open source code for parsing it as well.
var obj = JSON.parse(result);
alert('tableid is ' + obj.payload.config.tableid);