Given a block like this:
var foo = {"regexp":/^http:\/\//,
"fun":function(){},
}
What is a proper way to store it in JSON?
You have to store the RegExp as a string in the JSON object. You can then construct a RegExp object from the string:
// JSON Object (can be an imported file, of course)
// Store RegExp pattern as a string
// Double backslashes are required to put literal \ characters in the string
var jsonObject = { "regex": "^http:\\/\\/" };
function fun(url) {
var regexp = new RegExp(jsonObject.regex, 'i');
var match;
// You can do either:
match = url.match(regexp);
// Or (useful for capturing groups when doing global search):
match = regexp.exec(url);
// Logic to process match results
// ...
return 'ooga booga boo';
}
As for functions: they should not be represented in JSON or XML anyway. A function may be defined as an object in JS, but its primary purpose is still to encapsulate a sequence of commands, not serve as a wrapper for basic data.
You can't. JSON is for data only, not code. There's no way to transfer functions, unless you can transform it to a string first.
You could do something like this...
Method
JSONEX = {
stringify: function(obj){
var jsonified = {}
// loop through object and write string and type to newly stored data structure
for(i in obj)
jsonified[i] = {
// some voodoo to determine the variable type
type: Object.prototype.toString.call(obj[i]).split(/\W/)[2],
value: obj[i].toString()
}
return JSON.stringify(jsonified)
},
parse: function(json){
objectified = {}
obj = JSON.parse(json)
// loop through object, and handle parsing of string according to type
for(i in obj)
if(obj[i].type == "RegExp"){
var m = obj[i].value.match(/\/(.*)\/([a-z]+)?/)
objectified[i] = new RegExp(m[1],m[2]);
} else if(obj[i].type == "String"){
objectified[i] = obj[i].value
} else if(obj[i].type == "Function"){
// WARNING: this is more or less like using eval
// All the usual caveats apply - including jailtime
objectified[i] = new Function("return ("+obj[i].value+")")();
}
// ADD MORE TYPE HANDLERS HERE ...
return objectified
}
}
Usage
myThing = {
regex: new RegExp("123","g"),
text: "good",
func: function(x){
return x * x
}
}
json = JSONEX.stringify(myThing)
// "{"regex":{"type":"RegExp","value":"/123/g"},"text":{"type":"String","value":"good"},"func":{"type":"Function","value":"function (x) {\n return x * x;\n}"}}"
obj = JSONEX.parse(json)
// native object representing original object
N.B.
Almost a good solution, but does not work with regex (for me anyway)
// doing this: jsonPlus.stringify(myThing)
// just stores `regex` as an empty object
In core JSON, there isn't; the JSON spec only allows for primitive values (string/numbers/boolean/null), and arrays and objects.
For those who's still looking for an answer:
with plagin JSONfn you can serialize javascript object with
- Functions
- Regexp
- Date
and re-create object from this string.
Documentation: http://www.eslinstructor.net/jsonfn/
--Vadim
It is not JSON, but it is a form of serialization: foo.toSource()
gives a string representation: "({regexp:/^http:\\/\\//, fun:(function () {})})"
. Using bar = eval(foo.toSource());
assigns a new object with a regex and a function to bar
.
I don't know how well it is supported. Several website mention that it is gecko-only, although they are two years old. I currently only have access to Firefox, so you test whether it works in the browsers you want to support (probably IE, Chrome, Safari and Opera).
I've used and would recommend serialize-javascript npm package from yahoo. It can serialize JSON with functions and regex specifically and handles other cases.
From their docs:
var serialize = require('serialize-javascript');
const serialized = serialize({
str : 'string',
num : 0,
obj : {foo: 'foo'},
arr : [1, 2, 3],
bool : true,
nil : null,
undef: undefined,
fn: function echo(arg) { return arg; },
re: /([^\s]+)/g
});
produces
'{"str":"string","num":0,"obj":{"foo":"foo"},"arr":[1,2,3],"bool":true,"nil":null,"fn":function echo(arg) { return arg; },"re":/([^\\s]+)/g}'
which can be hydrated with
const obj = JSON.parse(serialized)
This can be verified by looking at their unit tests.
TL;DR:
Storing both as objects seems the best to me:
{
"regexp": {
"body": "^http:\\/\\/",
"flags": ""
},
"fun": {
"args": [],
"body": ""
}
}
RegExps:
There are already a lot of great answers for storing regexps: store them as raw strings, so that one can use RegExp
constructor to create an actual regexp from strings.
My addition would be to keep in mind flags. The OP might not need it, but it is definitely has to be addressed. RegExp
constructor takes flags in the form of a string as its second parameter. So the contract for JSON-stored regexp would be:
interface JSONStoredRegExp {
body: string; // "" (empty string) for empty regexp
flags: string; // "" (empty string) for zero flags
}
... and, for example, this JSON:
{
"regexp": {
"body": "abc",
"flags": "gi"
}
}
... would produce this regexp:
RegExp(json.regexp.body, json.regexp.flags);
/abc/gi
Functions:
Unless a given function is pure, it seems weird to me to transfer it via JSON. Also, the code of such an algorithm is likely incompatible with any language, other than JavaScript.
Anyway, if that is still necessary to do, I would recommend the same approach: transfer functions as an object, rather than a string. One can also use Function
constructor to create functions from serialized list of arguments and body.
interface JSONStoredFunction {
args: string[]; // [] (empty array) for zero arguments
body: string; // "" (empty string) for no-op function
}
Function
constructor takes body as its last argument, and each of the parameters has to be passed separately; so this JSON:
{
"fun": {
"args": [ "x", "y" ],
"body": "return x + y;"
}
}
... will produce this function:
Function(...json.fun.args, json.fun.body);
function anonymous(x, y) { return x + y; }
It might be inconvenient to use ...
the spread operator. In that case, using .apply
might help:
Function.apply(null, json.fun.args.concat(json.fun.body));
All answers above is right, instead of you can save this part of code as a string and then do eval()
var sCode = 'var oFoo = {"regexp": new RegExp("/^http:\/\//"), "fun": function() {}}';
eval(sCode);
console.log(oFoo);
来源:https://stackoverflow.com/questions/8328119/can-i-store-regexp-and-function-in-json