#javascript #json #typescript
#javascript #json #typescript
Вопрос:
У меня есть объект JSON, проанализированный из строки.
Допустим, у этого объекта есть свойство с именем «Name», значением которого может быть простая строка или массив строк или даже объект, хранящий некоторую информацию о нем.
Во время выполнения я хочу иметь возможность находить тип значения (строка / массив / объект) и, если это объект, приводить его к правильному классу и запускать метод на основе этого.
У меня есть идея о том, как я собираюсь это сделать, но единственная проблема заключается в том, что я не уверен, как преобразовать объект в правильный тип.
Например, у меня есть класс, который принимает две строки, и другой класс, который принимает строку и число. Я хочу, чтобы программа увидела, какому из них он соответствует, а затем привела его к правильному классу.
Надеюсь, я выразился достаточно ясно, если потребуется дополнительная информация, пожалуйста, дайте мне знать.
Редактировать:
Вот решение, которое я использовал, чтобы заставить это работать (по крайней мере, для меня, это может быть не лучшим решением в каждом конкретном случае).
У меня есть абстрактный класс, называемый Parser
export abstract class Parser {
abstract parse(): string;
clone(dataObject: object): Parser {
if (this.validateData(dataObject) == false) return null;
return this.cloneObject(dataObject);
}
protected abstract cloneObject(dataObject: object): Parser;
protected validateData(data: object): boolean {
const parserKeys = Object.keys(this);
const dataKeys = Object.keys(data);
for (let i = 0; i < parserKeys.length; i ) {
const parserKeyName = parserKeys[i];
if (typeof this[parserKeyName] === "function") continue;
const index = dataKeys.indexOf(parserKeyName);
if (
index == -1 ||
typeof data[dataKeys[i]] !== typeof this[parserKeyName]
)
return false;
}
return true;
}
}
У него есть метод validateData, который принимает объект (обычно объект JSON) и проверяет, что у него есть все переменные, имеющиеся в анализаторе.
Если данные действительны, он вызовет защищенный абстрактный метод, называемый cloneObject.
Вот простой класс под названием MinMaxParrser, который расширяет синтаксический анализатор
import { Parser } from "./Parser";
import { randomNumber } from "./utils";
export class MinMaxParser extends Parser {
min: 0;
max: 1;
constructor() {
super();
this.min = 0;
this.max = 1;
}
parse(): string {
return randomNumber(this.min, this.max).toString();
}
cloneObject(dataObject: object): MinMaxParser {
let newParser = new MinMaxParser();
newParser.min = dataObject["min"];
newParser.max = dataObject["max"];
return newParser;
}
}
Как вы можете видеть, у него есть метод cloneObject, который в основном возвращает экземпляр нового MinMaxParser
И, наконец, в основной программе у меня есть постоянный массив всех доступных анализаторов путем объявления объекта «sample»
const availableParsers: Parser[] = [new MinMaxParser()];
Когда я хочу найти действительный анализатор, я использую этот метод
private findValidParser(data: Object): Parser {
let found = null;
availableParsers.forEach(parser => {
let clone = parser.clone(data);
if (clone !== null) {
found = clone;
}
});
return found;
}
findValidParser возвращает мне синтаксический анализатор или null, я проверяю наличие null, и если это не null, я могу безопасно вызвать созданный мной метод parse ().
Комментарии:
1. Не могли бы вы добавить несколько примеров вместо того, чтобы так подробно описывать их словами, пожалуйста?
2. Прежде чем продолжить, пожалуйста, прочитайте о JSON .
3. Вы пробовали использовать typeof, возможно, с переключателем / регистром?
4.
Object.prototype.toString.call(what_ever_object)
возвращает «класс» объекта.5. Это может быть просто неправильное использование терминов, но вы не можете привести литерал JSON (который вы получаете при разборе строки) к классу. Однако вы можете преобразовать его в интерфейс.
Ответ №1:
Используйте typeof
и перегружайте функции, чтобы получить лучшие подсказки по типу:
// narrow down types to get better typings
function parse(a: string, b: {}, c: string): Parser1;
//...
// implement generically
function parse(a: any, b: any, c: any): Parser {
if(typeof a === "string" amp;amp; typeof b === "object" amp;amp; typeof c === "string") {
return Parser1.parse(a, b, c);
} /*...*/
}
Комментарии:
1. Спасибо, это вроде как то, что я искал. Но вместо того, чтобы делать много инструкций if, я, вероятно, создам функцию, которая посмотрит на класс и сравнит его для меня, а затем создаст экземпляр на основе этого (хотя это, вероятно, будет немного халтурно). Я опубликую решение с полным кодом позже сегодня, когда вернусь домой и закодирую его. И если я столкнусь с другой проблемой, я опубликую здесь. Спасибо.
Ответ №2:
Используйте следующее, чтобы проверить каждый
let obj = {};
let str = '';
let num = 0;
let array = [];
console.log(Array.isArray(array))
console.log(typeof obj === 'object')
console.log(typeof str === 'string')
console.log(!isNaN(num))
Комментарии:
1. Спасибо. Но с чем я действительно борюсь, так это с тем, является ли тип объектом, я хочу сделать его экземпляром класса на основе данных объекта.
2. сделать его экземпляром класса? вы хотите преобразовать объект в экземпляр класса? должно быть, это уже экземпляр, иначе вы не можете.