firebase dbを使おうとしていますが、FirebaseのヘルプやFAQに記載されていない非常に重要な制限が見つかりました。
最初の問題はその記号です:ドット '。'キーで禁止、
つまり、firebase 拒否(理由は不明) 次:
nameRef.child('[email protected]').set('Pirat');
このようなキーを追加しようとすると、キー '/'のスラッシュに関する2番目の問題
{'02/10/2013': true}
Firebaseでは、次のことを確認できます。
'02': {
'10': {
'2013': true
}
}
それを(自動的に)解決する方法について何かアイデアはありますか?すべての記号を含む文字列キーであるというフラグを設定できますか?もちろん、書き込み前と読み取り後に毎回データを解析/復元できますが...
ところで '。' '/'-Firebaseのすべての制限付きシンボル?
子を追加する_02/10/2013
_がFirebaseに構造を作成する理由は、スラッシュによって新しいレベルが作成されるためです。
したがって、次のようなものを使用していると私が想定している行:firebaseRef.child('02/10/2013').set(true)
はfirebaseRef.child('02').child('10').child('2013').set(true)
と同等です。
参照キー名に次の文字を使用できないという問題を回避するには( ソース )、
- 。 (限目)
- $(ドル記号)
- [(左角括弧)
- ](右角括弧)
- #(ハッシュまたはポンド記号)
- /(スラッシュ)
私の知る限り、Firebaseはnotを提供していないため、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('[email protected]').replace(/\./g, '%2E') //results in "Henry%2EMorgan%40caribbean%2Esea"
encodeURIComponent('02/10/2013'); //results in "02%2F10%2F2013"
_
最終結果はどちらもキー名としてFirebaseに安全に挿入できるため、他の唯一の懸念事項は、Firebaseから読み取った後のデコードであり、replace('%2E', '.')
と単純なdecodeURIComponent(...)
で解決できます。 。
私自身も同じ問題に直面し、この目的のために firebase-encode を作成しました。
選択した回答とは異なり、 firebase-encode は安全でない文字(./[]#$)と%(エンコード/デコードの仕組みのために必要)のみをエンコードします。 encodeURIComponent
がそれらをエンコードしている間、firebaseキーとして安全に使用できる他の特殊文字を残します。
詳細のソースコードは次のとおりです。
// http://stackoverflow.com/a/6969486/692528
const escapeRegExp = (str) => str.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g, '\\$&');
const chars = '.$[]#/%'.split('');
const charCodes = chars.map((c) => `%${c.charCodeAt(0).toString(16).toUpperCase()}`);
const charToCode = {};
const codeToChar = {};
chars.forEach((c, i) => {
charToCode[c] = charCodes[i];
codeToChar[charCodes[i]] = c;
});
const charsRegex = new RegExp(`[${escapeRegExp(chars.join(''))}]`, 'g');
const charCodesRegex = new RegExp(charCodes.join('|'), 'g');
const encode = (str) => str.replace(charsRegex, (match) => charToCode[match]);
const decode = (str) => str.replace(charCodesRegex, (match) => codeToChar[match]);
私はこれを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;
}
文字の制限については、 https://www.firebase.com/docs/creating-references.html で説明されています-'。'、 '/'、 '['、 ']'、 'は使用できませんキー名の# '、および' $ '。これらの文字を自動的にエスケープする方法はありません。それらの使用を完全に回避するか、独自のエスケープ/エスケープ解除メカニズムを作成することをお勧めします。
Swift 3を使用している場合、これは私にとってはうまくいきます(遊び場で試してみてください):
var str = "this.is/a#crazy[string]right$here.$[]#/"
if let strEncoded = str.addingPercentEncoding(withAllowedCharacters: .alphanumerics) {
print(strEncoded)
if let strDecoded = strEncoded.removingPercentEncoding {
print(strDecoded)
}
}
キー用の「自動」組み込みFireBaseエンコーダーが表示されません。
これがJavaソリューションです。
Josue.0の回答を簡略化したバージョンで作成しましたが、彼のバージョンでは問題が発生する可能性があるため、より適切なコードだと思います。多くの人がコードで_Pまたは_Dを使用するため、より複雑でありそうもない必要があります。
public static String encodeForFirebaseKey (String s) {
s = s.replace(".", "_P%ë5nN*")
.replace("$", "_D%5nNë*")
.replace("#", "_H%ë5Nn*")
.replace("[", "_Oë5n%N*")
.replace("]", "_5nN*C%ë")
.replace("/", "*_S%ë5nN")
;
return s;
}
public static String decodeFromFirebaseKey(String s) {
s = s.replace("_P%ë5nN*", ".")
.replace("_D%5nNë*", "$")
.replace("_H%ë5Nn*", "#")
.replace("_Oë5n%N*", "[")
.replace("_5nN*C%ë", "]")
.replace("*_S%ë5nN", "/");
return s;
個人的に、私は私が遭遇したこの同じ問題のための単純で簡単なハックを見つけました
_dateTime string
_を取得し、replace('/','|')
を使用して変換しました
結果は、_2017|07|24 02:39:37
_ではなく_2017/07/24 02:39:37
_のようになります。
私はこの問題に悩まされたので、@ sushain97から答えを受け取り(ありがとう!)、ディープエンコーダー/デコーダーを構築しました。
https://www.npmjs.com/package/firebase-key-encode
基本的な使用法:
var firebaseKeyEncode = require('firebase-key-encode');
firebaseKeyEncode.encode('my.bad.key');
// Output: my%2Ebad%2Ekey
深い使用法:
var firebaseKeyEncode = require('firebase-key-encode');
var badTree = {
"pets": [
{
"jimmy.choo": 15}
],
"other.key": 5
}
firebaseKeyEncode.deepEncode(badTree);
// Output: {
// "pets": [
// {
// "jimmy%2Echoo": 15}
// ],
// "other%2Ekey": 5
// }