抽象列表中具体类型的Typescript反序列化(序列化JSON.NET)

时间:2018-12-17 12:47:34

标签: typescript json.net

我有一个从API返回的对象,该对象包含一个由许多不同的具体类型填充的列表(显然具有相同的基础)。我想将这些项目映射到特定的Typescript接口模型类型,而无需花费大量精力。

是否存在使用JSON.NET写入JSON对象并将其(自动或通过映射配置)映射到Typescript接口/模型实例的“ $ type”属性的库或技术?还有另一种方法不是手动映射吗?

注意:在我的场景中,.NET类名称空间在进行序列化时已从API中剥离,用于客户端调用(例如,{ $type: 'Foo' }而不是{ $type: 'MyApp.Models.Foo' }

1 个答案:

答案 0 :(得分:0)

如果必须具有类实例而不是普通对象,则必须通过反射遍历对象树并递归反序列化它。

这是一个简单的草图:

class Foo
{
    name: string;

    log()
    {
        console.log("Name: " + this.name);
    }
}

class Bar
{
    age: number;

    log()
    {
        console.log("Age: " + this.age);
    }
}

class MyObject
{
    items: (Foo | Bar)[];
}

/** Type mappings. */
const types = {
    "MyObject": MyObject,
    "Foo": Foo,
    "Bar": Bar
};

const deserialize = <R = any>(instance: { $type: string }): R =>
{
    // Construct class instance.
    const ctor = types[instance.$type];
    const obj = new ctor();

    // Assign/deserialize all properties of the object.
    for (const key in instance)
    {
        const val = instance[key];
        if (val == null)
        {
            obj[key] = val;
        }
        else
        {
            if (typeof val.$type == 'string')
                obj[key] = deserialize(val);
            else if (Array.isArray(val))
                obj[key] = val.map(item => item == null ? item : deserialize(item));
            else
                obj[key] = val; // Probably some standard type 
        }
    }

    return obj;
}
const json = {
    $type: 'MyObject',
    items: [
        { $type: "Foo", name: "Steve" },
        { $type: "Bar", age: 42 },
    ]
};
const test = deserialize<MyObject>(json);

test.items.forEach(item => item.log());

这可以正确打印:

Name: Steve
Age: 42