Здесь нужно помнить 2 вещи:
Когда вы определяете методы получения и установки, они не становятся методами экземпляра после переноса в Javascript, но добавляются в прототип с помощью Object.defineProperty. Это означает, что вы не получите их, просто используя JSON.stringify
Передача массива replacer в JSON.stringify и указание использовать только значения прототипа, но это не так работать с вложенными объектами. По правде говоря, JSON.stringify будет анализировать только свойства с этим именем, независимо от того, где они находятся в структуре объекта.
Например,
let a = {
user: "Foo",
data: {
name: "Bar"
}
};
JSON.stringify(a, ["user", "data"]);
выведет {"user":"Foo","data":{}}
, потому что даже если ключ вложенного объекта равен data
, сам объект не имеет свойств с именем [115 ] или data
Но
let a = {
user: "Foo",
data: {
user: "Bar"
}
};
JSON.stringify(a, ["user", "data"]);
будет выводить {"user":"Foo","data":{"user":"Bar"}}
, потому что вложенный объект имеет свойство, называемое user
, точно так же как его родитель
Я считаю, это поведение может сбивать с толку, но можно реализовать решение, создав метод, который получает все свойства всех интересующих вас объектов. В Typescript я не нашел способа проверить, реализует ли класс интерфейс (или расширяет класс), поэтому мне пришлось немного поработать с тем, что, как я знаю, работает, хотя это не так уж «элегантно».
abstract class Stringifyiable {
private isStringifyiable(value): boolean {
return value != null && (typeof value === 'object' || typeof value === 'function') && value['getJsonKeys'] && typeof value['getJsonKeys'] === 'function';
}
public getJsonKeys(): string[] {
let keys = Object.keys(this.constructor.prototype);
keys.forEach(key => {
if (this.isStringifyiable(this[key])) {
keys = keys.concat(this[key].getJsonKeys());
}
});
return keys;
}
public toJSONString(): string {
return JSON.stringify(this, this.getJsonKeys());
}
}
class Foo extends Stringifyiable {
private _id: number;
private _desc: string;
private _user: Bar;
constructor(id: number, desc: string, user: Bar) {
super();
this._id = id;
this._desc = desc;
this._user = user;
}
public get id(): number {
return this._id;
}
public set id(value: number) {
this._id = value;
}
public get desc():string {
return this._desc;
}
public set desc(value: string) {
this._desc = value;
}
public get user(): Bar {
return this._user;
}
public set user(value: Bar) {
this._user = value;
}
}
class Bar extends Stringifyiable {
private _name: string;
private _surname: string;
constructor(name: string, surname: string) {
super();
this._name = name;
this._surname = surname;
}
public get name(): string {
return this._name;
}
public set name(value: string) {
this._name = value;
}
public get surname():string {
return this._surname;
}
public set surname(value: string) {
this._surname = value;
}
}
let foo = new Foo(1, 'something', new Bar('foo', 'bar'));
//this will output {"id":1,"desc":"something","user":{"name":"foo","surname":"bar"}}
foo.toJSONString();
Будьте осторожны с циклическими ссылками, потому что это войдет в бесконечный цикл (хотя я уверен, что это можно исправить).
Вам, вероятно, будет нужна к оценке переменная, чтобы заменить им правильно. Один пример состоял бы в том, чтобы просто сделать
caminho=`eval "echo $caminho"`
Следует иметь в виду, что это повредится если caminho
содержит точки с запятой или кавычки, это будет также рассматривать обратные косые черты как выход, и если данные недоверяемы, необходимо заботиться, что Вы не цель инжекционного нападения.
Надежда, которая помогает.
Заключение в кавычки и расширение всегда хитро, особенно в ударе. Если Ваш собственный корневой каталог достаточно хорош, этот код работы (я протестировал его):
if test -z $caminho
then
caminho="${HOME}/IGRAFO"
else
case "$caminho" in
'~') caminho="$HOME" ;;
'~'/*) caminho="$HOME/${caminho#'~/'}" ;;
'~'*) echo "Case of '$caminho' is not implemented" 1>&2 ;;
esac
fi
Возможно, используйте /home/${USER}
вместо этого заменяя Вашим высоким каталогом уровня пользователя, если, если не /home
.