简体   繁体   English

JS / TS确定JSON对象是否实现了类或接口

[英]JS / TS determine if a JSON object implements a class or interface

I have a JSON object parsed from a string. 我有一个从字符串解析的JSON对象。
Let's say this object has a property called "Name" the value of it can be a simple string or an array of strings or even an object that store some information about it. 假设这个对象有一个名为“Name”的属性,它的值可以是一个简单的字符串,也可以是一个字符串数组,甚至是一个存储有关它的信息的对象。

In runtime I want to be able to find the value type (string/array/object) and if it is an object cast it into the correct class and run a method based on that. 在运行时,我希望能够找到值类型(字符串/数组/对象),如果它是一个对象,则将其转换为正确的类并运行基于该方法的方法。

I have the idea on how I am going to go about this but the only problem is that I am not sure how to convert the object to the correct type. 我有关于如何解决这个问题的想法,但唯一的问题是我不确定如何将对象转换为正确的类型。

For example, I have a class which accepts two strings and another class that accepts a string and a number. 例如,我有一个接受两个字符串的类和另一个接受字符串和数字的类。 I want the program to see which one it matches and then cast it to the correct class. 我希望程序看到它匹配哪一个,然后将它转换为正确的类。

Hope I was clear enough if more information is needed please let me know. 希望我很清楚,如果需要更多信息,请告诉我。

EDIT: 编辑:

Here is the solution I used to make this work (at least for me, it may not be the best solution in every case). 这是我用来完成这项工作的解决方案(至少对我而言,它可能不是每种情况下的最佳解决方案)。

I have an abstract class called Parser 我有一个名为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;
    }
}

It has the method validateData which takes an object (the JSON Object usually) and validate that it has all the variables the Parser has. 它有方法validateData,它接受一个对象(通常是JSON对象)并验证它具有Parser所具有的所有变量。 If the data is valid it will call a protected abstract method called cloneObject. 如果数据有效,它将调用名为cloneObject的受保护抽象方法。

Here is a simple class called MinMaxParrser that extends Parser 这是一个名为MinMaxParrser的简单类,它扩展了Parser

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;
        }
    }

As you can see, it has the cloneObject method which basically returns an instance of a new MinMaxParser 如您所见,它具有cloneObject方法,该方法基本上返回新MinMaxParser的实例

And finally, in the main program, I have a const array of all the available parsers by declaring a "sample" object 最后,在主程序中,我通过声明一个“sample”对象来获得所有可用解析器的const数组

const availableParsers: Parser[] = [new MinMaxParser()];

When I want to find a valid parser I use this method 当我想找到一个有效的解析器时,我使用这个方法

private findValidParser(data: Object): Parser {
    let found = null;
    availableParsers.forEach(parser => {
        let clone = parser.clone(data);
        if (clone !== null) {
            found = clone;
        }
    });

    return found;
}

The findValidParser returns me a parser or null, I check for null and if it is not null i can safely call the parse() method i created. findValidParser返回一个解析器或null,我检查null,如果它不为null,我可以安全地调用我创建的parse()方法。

Use the following to check each 使用以下方法检查每个

 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)) 

Use typeof and function overloads to get better type hints: 使用typeof和function重载来获得更好的类型提示:

// 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" && typeof b === "object" && typeof c === "string") {
   return Parser1.parse(a, b, c);
 } /*...*/
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM