I have this javascript file which looks like below:
var abc= {
"a" : {
"label": "Monthly",
"URL": "xyz.com",
"ArchTag": "M",
"archData": {
"Feb 2016":"20160229",
"Jan 2016":"20160129",
"Dec 2015":"20151231"
}}};
so I want a way to edit this and say add a new month detail. I guess its a json inside javascript. So how can one edit it in a standard way.
If you can rely on the data looking exactly like this every time then you can just hack off the bit that stops it being JSON:
json_data = json.loads('{' + json_file.read().partition('{')[2])
(or use a regex, or whatever you prefer for string manipulation)
You should still beware that JavaScript is not the same as JSON, so you need some confidence that what you're given will always be an assignment of a valid JSON associative array to a variable.
If, on the other hand, you're being passed arbitrary JavaScript and you're expected to evaluate it, then you have a much bigger problem to solve. What if someone gives you var xyz = "Monthly"; var abc = {"label" : xyz, "URL" : "xyz" + "." + "com"}?
You need a JavaScript engine to solve that more general problem, not just a JSON parser. For example, js2py claims to be a complete JavaScript engine written in Python, but I've never used it so I can't recommend or dis-recommend it.
There are also security issues to consider in executing code from untrusted sources, beyond those you consider if all you're doing is parsing JSON from an untrusted source. So if you need to use a JavaScript engine, make sure you properly understand how it is sandboxed.
Your code is Javascript, not JSON...
With this code in JS you just create a new Object.
But JSON IS NOT A LANGUAGE!!.!
Json is a solution to efficiency store/transmit datas (as assiocative arrays).
Just try to do not define abc:
Your JSON file:
{
"a" :
{
"label": "Monthly",
"URL": "xyz.com",
"ArchTag": "M",
"archData":
{
"Feb 2016":"20160229",
"Jan 2016":"20160129",
"Dec 2015":"20151231"
}
}
}
If you can not remove var abc of your file, read the file in a string, remove the first characters of the string and load the new string.
try:
with open(file) as json_file:
data = file.read()
json_data = json.loads(data[9:])
pprint(json_data)
except Exception as e:
print(e)
if it is not always written var abc then start your string at the first { index.
Actually the file content is not json because of the var you mentioned. you should remove that part dynamically:
json_text = json_file.read().replace('var abc=','')
json_data = json.dumps(json_text)
pprint(json_data)
You can use regex to replace the var assignment piece:
with open('file.txt') as json_file:
data = json_file.read()
data = re.sub(r'^var\s*\S*\s*=\s*', '', data)
json_data = json.loads(data)
Related
I have the following string:
var originalStr = "Test example <firstTag>text inside first tag</firstTag>, <secondTag>50</secondTag> end."
What's the best way to identify all tags, the correspondent tag name and their content? This is the kind of result I'm looking for.
var tagsFound =
[ { "tagName": "firstTag", "value": "text inside first tag" }
, { "tagName": "secondTag", "value": "50" }
]
HTML is very complicated to parse, so the best approach is to use a parser that already exists.
If you're doing this in a browser, you can use the one built into the browser: DOMParser.
If you're doing this in Node.js, there are several libraries to do it, such as jsdom. It provides an API almost identical to the one in web browsers.
Here's a jsdom example:
const dom = new JSDOM("<!doctype html>" + originalStr);
const doc = dom.window.document;
for (const childElement of doc.body.children) {
console.log(`${childElement.tagName} - ${childElement.textContent}`);
}
With your string, that would output:
FIRSTTAG - text inside first tag
SECONDTAG - 50
You'd write code using the DOM methods provided to create the output you're looking for. (Note the tag name normalization above; you may have to use nodeLocation to get the original capitalization if it matters to what you're doing.)
Depending on complexity of strings you dealing with - the simple regEx solution might work (it works for your string nicely:
var str = 'Test example <firstTag>text inside first tag</firstTag>, <secondTag>50</secondTag> end.';
var tagsFound = [];
str.replace(/<([a-zA-Z][a-zA-Z0-9_-]*)\b[^>]*>(.*?)<\/\1>/g, function(m,m1,m2){
// write data to result objcect
tagsFound.push({
"tagName": m1,
"value": m2
})
// replace with original = do nothing with string
return m;
});
// Displaying the results
for(var i=0;i<tagsFound.length; i++){
console.log(tagsFound[i]);
}
There will be a problem when self closing tags or tags containing other tags are taken into accont. Like <selfClosedTag/> or <tag><tag>something</tag>else</tag>
I discovered Javascript ES6 Template Literals today. Just one word: Awesome!
Question: How to store and load Template Literals as JSON? I load some files via XHR, followed by some JSON.parse() which doesn't support ` instead of ", so it seems one can't save Template Literals directly in the files.
Goal: To use this for dynamic strings and translation and to get rid of confusing stuff like ("Hello " + username + "! How are you?") which requires multiple strings to be stored for just one message, and instead save my stuff beautifully and simple as
`Hello, ${username}! How are you?`
where username points to the dynamic variable with the same name. Is that possible? If yes, how to achieve this? It's okay if i have to use a function to somehow convert the strings into Template Literals as long as it doesn't hit hard on the overall performance, but I would like to at least avoid eval.
You can create your own function to parse template literal,
function stringTemplateParser(expression, valueObj) {
const templateMatcher = /{{\s?([^{}\s]*)\s?}}/g;
let text = expression.replace(templateMatcher, (substring, value, index) => {
value = valueObj[value];
return value;
});
return text
}
console.log(stringTemplateParser('my name is {{name}} and age is {{age}}', {name: 'Tom', age:100}));
// output 'my name is Tom and age is 100'
You could always use JSON.stringify to enclose dynamic data:
const data = 'some value';
JSON.stringify({
data,
});
// expected: "{\"data\": \"some value\"}"
I found it easier to separate the problem in a few substrings of JSON. Create the key "message" and this key stores parts of the message. It also works well for i18n.
{
"message" : {
"_0": "first part ",
"_1": "after first variable. ",
"_2": "after another variable"
}
}
And then, after decoding it, you can access it like
${message._0}${variable}${message._1}${var2}${message._2}
Try json-templates. Looks like exactly what you're looking for.
So basically I have this code:
var string = '{name: "bob", height: 4, weight: 145}';
I would like to know if it is possible to convert that string into an object.
so that I can use
string.name, string.height, and string.weight
(I am retrieving the string variable from a database so I cannot just remove the quotes and make it an object in the first place)
eval, as suggested by Igor, will certainly work but is vulnerable to attack.
Instead you could use a library to parse it for you. There are options in the following link:
Eval is evil... So what should I use instead?
It seems that your string is malformed. In order to work with JSON.parse or even jQuery.parseJSON methods, your keys must have speech marks (" ) around them, like so:
var str = '{"name": "bob", "height": 4, "weight": 145}';
var obj = JSON.parse(str);
You can test this by adding console.log(obj); as the final line. Here is my jsFiddle example.
So try to see if you can pull down the data from the server in the format I have suggested and it can then easily be parsed into a JavaScript object.
I would not use string for a variable name, but:
var obj = eval(string);
alert(obj.name);
or you can use jQuery.parseJSON: api.jquery.com/jQuery.parseJSON.
I'm trying to insert some data from a proprietary JSON database into MongoDB for testing purposes. My data is currently in a json file in the format:
{ "_id": "213124123114",
"foo":bar",
"otherId": "2324242424",
...
}
To keep my test data relationships intact, I want to use sed to wrap all the _id and xxxId values with ObjectId(...)
My data would then look like:
{ "_id": ObjectId("213124123114"),
"foo":bar",
"otherId": ObjectId("2324242424"),
...
}
I would then take the data and insert it into mongo in the same format as displayed in the file.
I'm testing my regex in javascript, but the following assignment blows up:
var y = s/"_id":(\s?"[0-9]+"),/ObjectId($1)/gi
SyntaxError: Unexpected token :
Escaping the ':' doesn't seem to do anything.
When I remove the capture flag at the start, the regex assignment works as expected
var y = /"_id":(\s?"[0-9]+"),/
var p = "\"_id\": \"123123123121321212312\",";
y.test(p) === true
but I have no way to capture the value block I need to wrap.
Any ideas what I'm doing wrong?
Try this:
json.replace(/("(?:_id|otherId)": ?)("\d+")/g, '$1ObjectId($2)');
Here's a fiddle: http://jsfiddle.net/7WJBm/1/
This is going to sound really ghetto, but I need to print some Javascript to the browser screen so that it can be cut and pasted into another program.
I'm using JSON.stringify() from json2.js, however, its not escaping characters such as quotes and new lines (",\n) which are actually control parts of a JSON object and need to be escaped.
For example, I'd get strings like this that cause problems when importing into the other program:
{
string_property_01 : "He said "HI""; // The string terminates after "He said "
}
Are there any libraries that I can use to escape all the characters that I need to escape here?
Thanks!
Option #2
var g = {
sampleFunc2 : function (data) {
var dataAsText = JSON.stringify(data);
// w jquery
$('#debugArea').text(dataAsText);
}
}
// usage...
g.sampleFunc2({ id: "4", name: "John Smith" });
In markup:
<textarea id='debugArea' rows='10' cols='50'></textarea>
I do the following, its a beautiful hack.
var g = {
sampleFunc : function (data) {
var dataAsText = JSON.stringify(data);
var response = prompt('you can copy and paste this', dataAsText);
}
}
// usage...
g.sampleFunc({ id: "4", name: "John Smith" });
JavaScript prompt... gotta love it.
Are you sure this isn't just a browser rendering thing playing tricks on you? A JSON library is going to escape chars properly to give you a valid JSON string. Have you tried comparing the output of json2.js to the native JSON.stringify some browsers (like chrome) have?