Добавление данных Firebase, точек и косых черт
Я пытаюсь использовать firebase db, Я нашел очень важные ограничения, которые не описаны в справке firebase или FAQ.
первая проблема-это символ: точка '.- запрещено в ключах,
т. е. firebase отклонить (по неизвестной причине) следующий:
nameRef.child('Henry.Morgan@caribbean.sea').set('Pirat');
вторая проблема с прямыми косыми чертами в ваших клавишах '/', когда вы пытаетесь добавить ключ, как это
{'02/10/2013': true}
в firebase вы можете см.:
'02': {
'10': {
'2013': true
}
}
У вас есть идеи, как его решить (автоматически)? Может быть установлен какой-то флаг, что это строковый ключ со всеми символами? Конечно, я могу анализировать / восстанавливать данные каждый раз перед записью и после чтения, но...
кстати '.''/' - все ограниченные символы для военнослужащих ?
8 ответов
причина, что добавление ребенка 02/10/2013
создает структуру в Firebase, потому что прямые косые черты приводят к созданию нового уровня.
поэтому я предполагаю, что вы используете что-то похожее на: firebaseRef.child('02/10/2013').set(true)
эквивалентно firebaseRef.child('02').child('10').child('2013').set(true)
.
чтобы избежать проблем, связанных с невозможностью использовать следующие символы в именах ссылочных ключей (источник),
- . (точка)
- $ (доллар знак)
- [ (левая квадратная скобка)
- ] (правая квадратная скобка)
- # (хэш или подписать фунт)
- / (косая черта)
мы можем использовать одну из встроенных функций кодирования JavaScript, поскольку, насколько я могу судить, Firebase делает не обеспечьте встроенный метод для этого. Вот прогон, чтобы увидеть, что является наиболее эффективным для наших целей:
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
. Однако, это не решает все наши проблемы. The .
символ по-прежнему создает проблему, как показано в приведенном выше тесте и пытается encodeURIComponent
ваш адрес электронной почты. Мое предложение состояло бы в том, чтобы связать функцию замены после encodeURIComponent
чтобы иметь дело с периодами.
вот как будет выглядеть решение для ваших двух примеров:
encodeURIComponent('Henry.Morgan@caribbean.sea').replace(/\./g, '%2E') //results in "Henry%2EMorgan%40caribbean%2Esea"
encodeURIComponent('02/10/2013'); //results in "02%2F10%2F2013"
поскольку оба окончательных результата безопасны для вставки в a Firebase как ключевое имя, единственная другая проблема-декодирование после чтения из Firebase, которое можно решить с помощью replace('%2E', '.')
и просто decodeURIComponent(...)
.
ограничения символов задокументированы в https://www.firebase.com/docs/creating-references.html - вы не можете использовать '.', '/', '[', ']', '#', и " $ " в ключевых именах. Не существует автоматического способа избежать этих персонажей, я бы рекомендовал избегать их использования или создания собственного побега/механизм снятия.
Я сам столкнулся с той же проблемой, и я создал firebase-encode для этой цели.
в отличие от выбранного ответа, firebase-encode кодирует только небезопасные символы (./ []#$) и % (необходимо из-за того, как работает кодирование/декодирование).
Он оставляет другие специальные символы, которые безопасны для использования в качестве ключа firebase в то время как encodeURIComponent
будет кодировать их.
вот исходный код для детали:
// 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;
}
Если вы используете 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)
}
}
Я разозлился на эту проблему, поэтому я взял ответ от @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
// }
лично я нашел простой и легкий хак для этой же проблемой я столкнулся
взял dateTime string
и преобразовать его с помощью replace('/','|')
результат будет что-то вроде этого 2017|07|24 02:39:37
вместо 2017/07/24 02:39:37
.
Я не вижу "автоматического" встроенного кодировщика 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;