2
1

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.

Google Apps ScriptのPropertiesServiceでキーに数値文字列を使うとハマる

Last updated at Posted at 2019-11-23

概要

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のオブジェクトにおいて、プロパティ名に数値や数値文字列を使った時の挙動を確認する。

test1.gs
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になる。

test2.gs
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ペアなら正しい値が取り出せる。

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

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?