概要
Google Apps Scriptには永続的なKey-ValueストアとしてPropertiesServiceがある。これは単独のKey-ValueペアをgetProperty/setPropertyできるだけでなく、複数のKey-Valueペアをオブジェクトとして表現しsetPropertiesすることもできるし、getPropertiesですべてのKey-Valueをオブジェクトとして取り出すこともできる。しかしKeyとして"123"のような数値文字列を使うとgetPropertiesでは簡単に値を取り出せなくなる。
Properties Service | Apps Script
JavaScriptのオブジェクトとしての挙動を確認
まずJavaScriptのオブジェクトにおいて、プロパティ名に数値や数値文字列を使った時の挙動を確認する。
function test1(){
var newProperties = {
82: "eighty two",
"83": "eighty three"
};
Logger.log(newProperties[82]); // "eighty two"
Logger.log(newProperties["82"]); // "eighty two"
Logger.log(newProperties[83]); // "eighty three"
Logger.log(newProperties["83"]); // "eighty three"
}
これは問題ない。プロパティ名として数値を使ってもただ相当する数値文字列として扱われるだけだ。
getPropertiesで取り出すと値がundefined
setProperties(newProperties)で保存しgetProperties()で取り出すと確かにオブジェクトが得られるが、そのオブジェクトから値を取り出そうとするとundefinedになる。
function test2(){
var newProperties = {
82: "eighty two",
"83": "eighty three"
};
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperties(newProperties);
var properties = scriptProperties.getProperties();
Logger.log(properties[82]); // undefined
Logger.log(properties["82"]); // undefined
Logger.log(properties[83]); // undefined
Logger.log(properties["83"]); // undefined
Logger.log(typeof properties); // object
Logger.log(Object.prototype.toString.call(properties)); //[object Object]
Logger.log(JSON.stringify(properties)); //{"82":"eighty two","83":"eighty three"}
properties[82] = "EIGHTY TWO";
Logger.log(properties["82"]); // "EIGHTY TWO"
}
PropertiesServiceから取り出したpropertiesは普通のJavaScriptのオブジェクトとは違うものなのだろうかと思ってtypeofしてみたりJSON.stringify(properties)してみたりしたが、特におかしなところは無かった。
getPropertyでひとつずつ取り出すと問題なし
getProperties()でKey-Valueペアをまとめて取り出したオブジェクトから値を取り出そうとするとundefinedだが、getProperty("82")のように一つのKey-Valueペアなら正しい値が取り出せる。
function test3(){
var newProperties = {
82: "eighty two",
"83": "eighty three"
};
var scriptProperties = PropertiesService.getScriptProperties();
scriptProperties.setProperties(newProperties);
Logger.log(scriptProperties.getProperty("82")); // "eighty two"
Logger.log(scriptProperties.getProperty("83")); // "eighty three"
}
結論
Google Apps ScriptのPropertiesServiceでは数値文字列をキーに使っちゃダメ。getPropertyで一つずつ取り出しているときには問題ないが、そのうちKey-Valueペアが増えてきてまとめてgetPropertiesしても値は取り出せない。どうしても取り出したければgetPropertiesで取り出したオブジェクトをJSON.stringifyしてからJSON.parseしてまともなオブジェクトに戻す。
想像
Google Apps ScriptはJavaScriptの実行エンジンとしてMozilla Rhinoのたぶん古いバージョンのものを使っている。getPropertiesで取り出したオブジェクトはRhino上では普通のオブジェクトと異なる何か変なJavaオブジェクトだったりするのではなかろうか。RhinoがJavaScriptのオブジェクトをどのような内部表現で扱っているのかは知らない。JSON.parseを実装しているJavaコードはそれをうまく扱うことができるんじゃないだろうか。いったんJSONな文字列になってしまえばこっちのものである。