概要
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な文字列になってしまえばこっちのものである。