22

firebase dbを使用しようとしましたが、firebase のヘルプや FAQ に記載されていない非常に重要な制限を見つけました。

最初の問題はその記号です: ドット '.' キーで禁止されている、

つまり、firebase reject (不明な理由で)次に:

        nameRef.child('Henry.Morgan@caribbean.sea').set('Pirat');

このようにキーを追加しようとすると、キー「/」のスラッシュに関する 2 番目の問題

        {'02/10/2013': true}

firebase では次のことがわかります。

         '02': {
             '10': {
                 '2013': true
             }
         }       

それを(自動的に)解決する方法はありますか?すべての記号を含む文字列キーであるというフラグを設定できますか? もちろん、書き込み前と読み取り後に毎回データを解析/復元できますが...

ところで '。' '/' - firebase のすべての制限付きシンボル ?

4

10 に答える 10

33

子を追加する02/10/2013と Firebase に構造が作成される理由は、スラッシュによって新しいレベルが作成されるためです。

したがって、次のようなものを使用していると思われる行は、次のものとfirebaseRef.child('02/10/2013').set(true)同等firebaseRef.child('02').child('10').child('2013').set(true)です。

参照キー名(source)に以下の文字が使用できない不具合を回避するため、

  • . (限目)
  • $ (ドル記号)
  • [ (左角かっこ)
  • ] (右角かっこ)
  • # (ハッシュまたはポンド記号)
  • / (スラッシュ)

私が知る限り、Firebaseにはそのための組み込みメソッドが用意されていないため、JavaScript の組み込みエンコーディング関数の 1 つを使用できます。ここでは、私たちの目的に最も効果的なものを確認するための概要を示します。

var forbiddenChars = '.$[]#/'; //contains the forbidden characters
escape(forbiddenChars); //results in ".%24%5B%5D%23/"
encodeURI(forbiddenChars); //results in ".%24%5B%5D%23%2F"
encodeURIComponent(forbiddenChars); //results in ".%24%5B%5D%23%2F"

明らかに、最も効果的なソリューションはencodeURIComponent. しかし、それですべての問題が解決するわけではありません。上記.のテストで示されているように、キャラクターはまだ問題を引き起こし、encodeURIComponentテスト用の電子メール アドレスを試しています。私の提案はencodeURIComponent、ピリオドに対処するために、後に置換関数をチェーンすることです。

2 つの例の場合、ソリューションは次のようになります。

encodeURIComponent('Henry.Morgan@caribbean.sea').replace(/\./g, '%2E') //results in "Henry%2EMorgan%40caribbean%2Esea"
encodeURIComponent('02/10/2013'); //results in "02%2F10%2F2013"

どちらの最終結果もキー名として Firebase に安全に挿入できるため、Firebase から読み取った後にデコードすることだけが懸念事項でreplace('%2E', '.')あり、単純なdecodeURIComponent(...).

于 2013-10-02T22:52:26.123 に答える
8

私はこれを Java 用に書きました (Java の実装を期待してここに来たので):

public static String encodeForFirebaseKey(String s) {
    return s
            .replace("_", "__")
            .replace(".", "_P")
            .replace("$", "_D")
            .replace("#", "_H")
            .replace("[", "_O")
            .replace("]", "_C")
            .replace("/", "_S")
            ;
}

public static String decodeFromFirebaseKey(String s) {
    int i = 0;
    int ni;
    String res = "";
    while ((ni = s.indexOf("_", i)) != -1) {
        res += s.substring(i, ni);
        if (ni + 1 < s.length()) {
            char nc = s.charAt(ni + 1);
            if (nc == '_') {
                res += '_';
            } else if (nc == 'P') {
                res += '.';
            } else if (nc == 'D') {
                res += '$';
            } else if (nc == 'H') {
                res += '#';
            } else if (nc == 'O') {
                res += '[';
            } else if (nc == 'C') {
                res += ']';
            } else if (nc == 'S') {
                res += '/';
            } else {
                // this case is due to bad encoding
            }
            i = ni + 2;
        } else {
            // this case is due to bad encoding
            break;
        }
    }
    res += s.substring(i);
    return res;
}
于 2016-09-18T18:45:48.943 に答える
8

文字制限はhttps://www.firebase.com/docs/creating-references.htmlに記載されています。「.」、「/」、「[」、「]」、「#」、および「$」は使用できません。キー名で。これらの文字を自動的にエスケープする方法はありません。使用を完全に避けるか、独自のエスケープ/エスケープ解除メカニズムを作成することをお勧めします。

于 2013-10-02T17:16:07.127 に答える
0

Python 実装

_escape = {'&': '&&',
       '$': '&36',
       '#': '&35',
       '[': '&91',
       ']': '&93',
       '/': '&47',
       '.': '&46'}

_unescape = {e: u for u, e in _escape.items()}


def escape_firebase_key(text):
    return text.translate(str.maketrans(_escape))


def unescape_firebase_key(text):
    chunks = []
    i = 0
    while True:
        a = text[i:].find('&')
        if a == -1:
            return ''.join(chunks + [text[i:]])
        else:
            if text[i+a:i+a+2] == '&&':
                chunks.append('&')
                i += a+2
            else:
                s = text[i+a:i+a+3]
                if s in _unescape:
                    chunks.append(text[i:i+a])
                    chunks.append(_unescape[s])
                    i += a+3
                else:
                    raise RuntimeError('Cannot unescape')

そして、いくつかのテストケース:

test_pairs = [('&hello.', '&&hello&46'),
              ('&&&', '&&&&&&'),
              ('some@email.com', 'some@email&46com'),
              ('#$[]/.', '&35&36&91&93&47&46')]
               
for u, e in test_pairs:
    assert escape_firebase_key(u) == e, f"escaped '{u}' is '{e}', but was '{escape_firebase_key(u)}'"""
    assert unescape_firebase_key(e) == u, f"unescaped '{e}' is '{u}', but was '{unescape_firebase_key(e)}'"
    
try:
    unescape_firebase_key('&error')
    assert False, 'Must have raised an exception here'
except RuntimeError as ex:
    assert str(ex) == 'Cannot unescape'

于 2021-07-02T17:17:23.837 に答える