But in the process of using JSON, I encountered a problem - this problem must have been encountered by everyone, that is: JSON does not define the transmission method of date and time.
Although json2.js has added support for Date functions and ISO-8601 date/time formats in an update in March this year, the support for dates in various commonly used development tools is still varied and strange. , there is no unity at all.
Moreover, in addition to date/time, sometimes we also need support for some classes or functions, which are not supported by JSON.
Some people may ask after seeing this: Since JSON is not supported, why not use other data description/transmission methods?
The reason is that JSON itself is a functional subset of JavaScript (its reference standard is ECMAScript), and anyone with a little knowledge of JavaScript can easily utilize JSON.
The easiest way to parse JSON is to directly use the eval function to execute it as JavaScript code. JSON is often used to pass between different applications on the Internet, so directly pass in the received JSON content. The eval function is very risky, so the format of JSON is strictly specified in the RFC document, and methods for testing its security are given.
This check method prohibits the function from running.
In short, because JSON is "occasionally" inconvenient to use, I started to use my brain to extend JSON.
After referring to RFC-4627, json2.js and some common JavaScript syntax shaders, I found that: although json2.js already has support for date/time, it uses grammatical analysis model, which means that if you don’t have a certain understanding of grammatical analysis, it is difficult to expand it; even if I have a little knowledge of grammatical analysis, it is not easy to expand it. , let alone future maintenance.
So I decided to use the simpler regular expression filtering method recommended in RFC-4627.
The basic implementation of this extension is as follows:
function Xenon(){}
var protoXenon = Xenon.prototype;
protoXenon.xeval = function(s){
var al = [], vl = [], ol = {};
function $(i, v){
// i = parseInt(i);
// return ol[i] || (ol[i] = v);
return ol. propertyIsEnumerable(i) ? ol[i] : (ol[i] = v);
}
for(var n in this)
if(this.propertyIsEnumerable(n) && typeof this[n] == 'function')
al.push(n), vl.push(this[n]);
return eval('0,function(' al '){return ' s ';}') .apply(this, vl);
};
protoXenon.safeXeval = function(s){
var T = this;
return (!/[^),:{}[]0 -9.- Eaeflnr-u nrt]/.test(
s.replace(/"(\.|[^"\])*"/g, '')
.replace(/([^ s:[,(] ?)(/g,function($0, $1){
// return T.propertyIsEnumerable($1) ? '' : $1 '(';
return T.propertyIsEnumerable($1) ? '' : '@';
})) || null) &&
this.xeval(s);
};
The basic usage is to create a xenon object , set a new member for it to enable the extension function.
You can add the extension function directly to the xenon object, or you can declare the function in the global scope and set the non-function type member value on the xenon object. >Example:
var xenon = new Xenon();
xenon.Array = 0;
xenon.$ = 0;
xenon.date = function(s){return new Date(s);};
var o = xenon.safeXeval('{ "list":Array(3,6,9),"created":$(1,date("Tue Jul 27 02:48:03 UTC 0800 2010")),"modified":$(1)}') ;
print(o.list);
print(o.created);
print(o.modified == o.created);
Note: This example cannot be executed directly as JScript.NET code. If you want to use it in JScript.NET, you must pass the string "unsafe" as the second parameter to the eval function.
Note 2: Adding "0," before the function keyword is for compatibility with the JScript engine used by IE - the current non-CLI version of the JScript engine cannot correctly understand the surrounding function definition in its eval implementation. The meaning of the parentheses will cause a syntax error.
Three function extensions are used in this example: Array is a JavaScript built-in function in the global scope; $ is a built-in function I implemented in XENON, which can reference the same object in multiple places; and date is a pair A wrapper for the Date constructor.
In the implementation of XENON, I did not allow it to support the new operator to create new objects. I did not find any reason to use new instead of directly using the extension function.
About the name: I originally planned to call it xJson, but then I thought it was a bit inferior, so I changed it to XEON (eXtensible ECMAScript Object Notation). Then I found that it seemed to be a registered trademark of Intel, so I added an extra N in the middle and it became XENON (eXtensible Native ECMAScript Object Notation). I looked it up in the dictionary and found that it was the name of a chemical element... so I just used it.
About security: In the process of designing the verification method, I tested as many character combinations as I could to avoid injection problems. But due to the lack of practical testing, and I am not good at things like grammatical analysis, it may not be absolutely safe. If anyone finds any security holes, please let me know so I can improve it.
When I have time in the future, I will make a simple function to convert ECMAScript objects to XENON; if I really have enough time, maybe I will also implement the conversion process including class names and constructors.