39
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JSONもどき(値として関数を持つ)をJSON.stringifyしたりJSON.parseしたりする

Last updated at Posted at 2013-10-09

値として関数を持った「JSONもどき」、使いたい時ってないですか?

皆さん、ご存知の通り、

var json_modoki = 
    {
        foo:100,
        boo:"sample text",
        hoge: {
           muda: "よろしく"
        },
        func: function() { console.log("hello world"+this.hoge.muda); },
        func2: function() { console.log("hello japan"+this.hoge.muda); }
    }

のような、値として関数を持っているようなものはJSONの仕様上、許されていません。
でも、こういう関数を持った「JSONもどき」って、たまに便利なときがありますよね。

ただ、問題なのがこういう「JSONもどき」ではJSON.stringifyによる文字列化や、
文字列化したものをJSON.parseで「JSONもどき」へ戻すことができないということ。

困りましたねー。

ということで、解決策を作ってみました。いや、私が作ったというか、白状しますと、2chで質問したらスーパーハカーな方が基本的なアイデアを教えてくれました。ありがとうございますw

基本方針

基本方針は、「JSONもどき内で値が関数のものは、文字列に変換する」です。
そして、「JSON.parseするときに、独自のパーサーを渡して、パーサー内で関数文字列をevalして関数に戻す」というものです。

詳細はコードを御覧ください。

function convertFunctionsToStringsInJSON(json_with_function) {
    var json = json_with_function;
    
    for (key in json) {
        if(typeof(json[key]) === "function") {
            json[key] = json[key].toString();
        }
    }
    
    return json;
}


var json = 
    {
        foo:100,
        boo:"sample text",
        hoge: {
           muda: "よろしく"
        },
        func: function() { console.log("hello world"+this.hoge.muda); },
        func2: function() { console.log("hello japan"+this.hoge.muda); }
    }


convertFunctionsToStringsInJSON(json);


console.log("stringified:"+JSON.stringify(json));


var jsonText = JSON.stringify(json);

var parser = function(k,v){return v.toString().indexOf('function') === 0 ? eval('('+v+')') : v};
var json2 = JSON.parse(jsonText, parser);

json2.func();
json2.func2();

上記のコードは、jsdo.itでも公開しています。

追記:もっと簡単なやり方

追記:関数の文字列化については、もっと簡単な方法があります。

Function.prototype.toJSON = Function.prototype.toString; とすると、JSON.stringifyの処理での関数の評価時に自動的にtoString()が発動します。

Function.prototype.toJSON = Function.prototype.toString;

var json = 
    {
        foo:100,
        boo:"sample text",
        hoge: {
           muda: "よろしく"
        },
        func: function() { console.log("hello world"+this.hoge.muda); },
        func2: function() { console.log("hello japan"+this.hoge.muda); }
    }

console.log("stringified:"+JSON.stringify(json));

var jsonText = JSON.stringify(json);

var parser = function(k,v){return v.toString().indexOf('function') === 0 ? eval('('+v+')') : v};
var json2 = JSON.parse(jsonText, parser);

json2.func();
json2.func2();

こちらもjsdo.itで公開しました。

最後に

いかがでしょうか。もちろん、こんな「JSONもどき」他のサービスとやりとりしたりなどすることはないと思いますが、自アプリ・自サービス内で内部的に使うのはアリだと思います。

そんなに多くないと思いますが、「このTips使えそう」と思ってくれた方がいらっしゃれば幸いです。

39
36
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
39
36

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?