Мне удалось сделать все, как ожидалось
@Injectable()
export class QueryService {
regex1: RegExp = new RegExp("^\\(([|&])(.*)\\)");
regex2: RegExp = new RegExp("\\(([&|]\\(.*\\)\\(.*?\\)).*?\\)|\\(.*?\\)", "g");
regex3: RegExp = new RegExp("\\((.*?)\\)");
constructor(){}
decode(query: string): Query {
if (!this.regex1.test(query)) {
console.error("Error while parsing query", query);
return;
}
const matches = query.match(this.regex1);
const parts = {
operator: matches[1] as QueryConditions,
content: matches[2].match(this.regex2)
};
return new Query(parts.operator, this._getQueryFields(parts.content));
}
private _getQueryFields(content: string[]): GenericObject {
const mapped: GenericObject = {};
forEach(content, (g) => {
if (this.regex1.test(g)) {
mapped.group = this.decode(g);
}
else {
//
const pair = g.match(this.regex3)[1].split("=");
mapped[pair[0]] = pair[1];
}
});
return mapped;
}
}
Где-то в моем приложении
source: string = new Query("&", {
foo: "bar",
goo: "car",
group: new Query("&", {
firstName: "john",
lastName: "doe"
})
}).generate();
decoded: Query = this._queryService.decode(source);
// source = (&(foo=bar)(goo=car)(&(firstName=john)(lastName=doe)))
// decode will produce a map
/* {
operator: "&",
fields: {
foo: "bar",
goo: "car",
group: {
operator: "&",
fields: {
firstName: "john",
lastName: "doe"
}
}
} */
Конечно, я могу работать с несколькими группами на одном уровне, но пока этого достаточно,Я буду постепенно улучшать код.