次のようなブロックがあるとします。
var foo = {"regexp":/^http:\/\//,
"fun":function(){},
}
それをJSONに保存する適切な方法は何ですか?
RegExpを文字列としてJSONオブジェクトに保存する必要があります。次に、文字列からRegExpオブジェクトを作成できます。
// 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';
}
関数については、JSONやXMLで表すべきではありません。関数はJSでオブジェクトとして定義できますが、その主な目的はコマンドのシーケンスをカプセル化することであり、基本的なデータのラッパーとしては機能しません。
できません。 JSONはデータ専用であり、コードではありません。最初に文字列に変換できない限り、関数を転送する方法はありません。
あなたはこのようなことをすることができます...
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
}
}
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
ほぼ良い解決策ですが、正規表現では機能しません(とにかく私にとって)
// doing this: jsonPlus.stringify(myThing)
// just stores `regex` as an empty object
まだ答えを探している人のために:
plaginJSONfnを使用すると、JavaScriptオブジェクトをシリアル化できます
この文字列からオブジェクトを再作成します。
ドキュメント: http://www.eslinstructor.net/jsonfn/
-ヴァディム
コアJSONにはありません。 JSON仕様 は、プリミティブ値(string/numbers/boolean/null)、および配列とオブジェクトのみを許可します。
オブジェクトとして両方を保存するのが私には最良のようです:
{
"regexp": {
"body": "^http:\\/\\/",
"flags": ""
},
"fun": {
"args": [],
"body": ""
}
}
正規表現を保存するための素晴らしい答えはすでにたくさんあります。それらを生の文字列として保存し、 RegExp
コンストラクタを使用して文字列から実際の正規表現を作成できるようにします。
私の追加はフラグを覚えておくことです。 OPはそれを必要としない場合がありますが、必ず対処する必要があります。 RegExp
コンストラクターは、2番目のパラメーターとして文字列の形式のフラグを取ります。したがって、JSONに格納された正規表現のコントラクトは次のようになります。
interface JSONStoredRegExp {
body: string; // "" (empty string) for empty regexp
flags: string; // "" (empty string) for zero flags
}
...そして、例えば、このJSON:
{
"regexp": {
"body": "abc",
"flags": "gi"
}
}
...この正規表現を生成します:
RegExp(json.regexp.body, json.regexp.flags);
/abc/gi
与えられた関数が純粋でない限り、JSON経由で転送するのは私には奇妙に思えます。また、そのようなアルゴリズムのコードは、JavaScript以外の言語と互換性がない可能性があります。
とにかく、それが依然として必要な場合は、同じアプローチをお勧めします。文字列ではなくオブジェクトとして関数を転送します。 Function
コンストラクターを使用して、引数と本文のシリアル化されたリストから関数を作成することもできます。
interface JSONStoredFunction {
args: string[]; // [] (empty array) for zero arguments
body: string; // "" (empty string) for no-op function
}
Function
コンストラクタは最後の引数として本体を受け取り、各パラメータは個別に渡す必要があります。したがって、このJSON:
{
"fun": {
"args": [ "x", "y" ],
"body": "return x + y;"
}
}
...この関数を生成します:
Function(...json.fun.args, json.fun.body);
function anonymous(x, y) { return x + y; }
...
スプレッド演算子 を使用するのは不便かもしれません。その場合、.apply
を使用すると役立つ場合があります。
Function.apply(null, json.fun.args.concat(json.fun.body));
私は使用しており、yahooの serialize-javascript npmパッケージをお勧めします。 JSONを関数と正規表現でシリアル化し、他のケースを処理できます。
彼らのドキュメントから:
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
});
作り出す
'{"str":"string","num":0,"obj":{"foo":"foo"},"arr":[1,2,3],"bool":true,"nil":null,"fn":function echo(arg) { return arg; },"re":/([^\\s]+)/g}'
水和することができます
const obj = JSON.parse(serialized)
これは 単体テスト を確認することで確認できます。
これはJSONではありませんが、シリアライゼーションの形式です:foo.toSource()
は文字列表現を提供します:"({regexp:/^http:\\/\\//, fun:(function () {})})"
。 bar = eval(foo.toSource());
を使用すると、正規表現と関数を含む新しいオブジェクトがbar
に割り当てられます。
どの程度サポートされているのかわかりません。いくつかのウェブサイトでは、2歳ですが、これはgeckoのみであると述べています。私は現在Firefoxにしかアクセスできないので、サポートしたいブラウザー(おそらくIE、Chrome、Safari、Opera)で動作するかどうかをテストします。
使用する良い動きがあります https://json5.org/ JSONで違法である多くのものが含まれているJSONの新しいスーパーセット
{
// comments
unquoted: 'and you can quote me on that',
singleQuotes: 'I can use "double quotes" here',
lineBreaks: "Look, Mom! \
No \\n's!",
hexadecimal: 0xdecaf,
leadingDecimalPoint: .8675309, andTrailing: 8675309.,
positiveSign: +1,
trailingComma: 'in objects', andIn: ['arrays',],
"backwardsCompatible": "with JSON",
}
github: https://github.com/json5/json5