将打字稿接口与递归 JSON 结合使用



我正在尝试使用 JSON 使产品的本体与其属性保持一致。下面提到的JSON结构是我正在考虑的。

每个产品(概念)都有两种类型的属性: 1. 数据属性 2.对象属性

使用 Protege 时这些属性的典型定义如下SO 线程

在 Protégé 中,有不同的选项卡用于创建对象属性和数据类型属性。如果属性应将个人与个人相关联,则它必须是对象属性,如果它将个人与文本相关联,则它必须是数据类型属性。

我认为每个属性都具有以下属性:

name: string
url: string
type: dataprop or objprop
objPropSource: available only for Objproperties

我已经绘制了一个小型递归JSON,如下所示:

{
"name": "chair",
"url": "http://namespace.org#chair",
"type": "main",
"properties": [
{
"name": "height",
"url": "http://namespace.org#height",
"type": "dataprop"
},
{
"name": "width",
"url": "http://namespace.org#width",
"type": "dataprop"
},
{
"name": "horizontalsurface",
"url": "http://namespace.org#horizontalsurface",
"type": "objprop",
"objPropSource": "http://namespace.org#hasHorizontalSurface",
"properties": [
{
"name": "Legislation",
"url": "http://namespace.org#legislation",
"type": "objprop",
"objPropSource": "http://namespace.org#compliesWithLegislation",
"properties": [
{
"name": "hasLegislationName",
"url": "http://namespace.org#hasLegislationName",
"type": "dataprop"
}
]
}
]
},
{
"name": "legislation",
"url": "http://namespace.org#legislation",
"type": "objprop",
"objPropSource": "http://namespace.org#compliesWithLegistion",
"properties": [
{
"name": "hasLegislationName",
"url": "http://namespace.org#hasLegislationName",
"type": "dataprop"
}
]
}
]
}

在某种程度上,结构为椅子提供了一个二叉树,该椅子将heightwidth等作为数据属性horizontalsurfacelegislation作为对象属性

JSON 到打字稿中的接口

我使用 JSON 到 TS 在线转换器查看如何将 JSON 转换为打字稿接口,结果如下:

interface RootObject {
name: string;
url: string;
type: string;
properties: Property3[];
}
interface Property3 {
name: string;
url: string;
type: string;
objPropSource?: string;
properties?: Property2[];
}
interface Property2 {
name: string;
url: string;
type: string;
objPropSource?: string;
properties?: Property[];
}
interface Property {
name: string;
url: string;
type: string;
}

推理

我推断使用递归 JSON 接口的 aprroach 是不可扩展的,因为产品的这种本体可以扩展到 1000 个属性和属性中的属性。如上所述,示例显示父属性中的每个属性都会继续创建接口。

期望

我应该期望使用具有这种 JSON 结构的打字稿接口,还是应该坚持创建一个类,然后遵循创建二叉树的传统方法,即。

export class leaf {
name: string;
url: string;
type: string;
children: leaf[] = [];
}

然后编写递归直到解析完整的结构?

TL;博士

Typescript 接口可以用于大型递归 JSON 结构吗?

你应该能够很好地将该结构表示为递归接口:

interface Property {
name: string;
url: string;
type: string;
objPropSource?: string;
properties?: Property[];
}

您尝试使用的 JSON 到 TS 转换器似乎没有识别结构递归性质的功能。

工作示例:

interface Property {
name: string;
url: string;
type: string;
objPropSource?: string; // optional property
properties?: Property[];
};
var p: Property = JSON.parse(getJson());
alert(p.properties[2].properties[0].name);
alert(p.properties[3].objPropSource);


function getJson() {
return `{
"name": "chair",
"url": "http://namespace.org#chair",
"type": "main",
"properties": [
{
"name": "height",
"url": "http://namespace.org#height",
"type": "dataprop"
},
{
"name": "width",
"url": "http://namespace.org#width",
"type": "dataprop"
},
{
"name": "horizontalsurface",
"url": "http://namespace.org#horizontalsurface",
"type": "objprop",
"objPropSource": "http://namespace.org#hasHorizontalSurface",
"properties": [
{
"name": "Legislation",
"url": "http://namespace.org#legislation",
"type": "objprop",
"objPropSource": "http://namespace.org#compliesWithLegislation",
"properties": [
{
"name": "hasLegislationName",
"url": "http://namespace.org#hasLegislationName",
"type": "dataprop"
}
]
}
]
},
{
"name": "legislation",
"url": "http://namespace.org#legislation",
"type": "objprop",
"objPropSource": "http://namespace.org#compliesWithLegistion",
"properties": [
{
"name": "hasLegislationName",
"url": "http://namespace.org#hasLegislationName",
"type": "dataprop"
}
]
}
]
}`;
}

两个可能的帮手,方便将来使用。

type MakeRecusive<Keys extends string, T> = {
[K in Keys]: T & MakeRecusive<K, T>
} & T

type MakeRecusiveObectKeys<TKeys extends string, T> = {
[K in keyof T]: K extends TKeys ? T[K] & MakeRecusive<K, T[K]>: T[K]
}

分辨器类型:

type BaseTypes = 'dataprop' | 'objprop'
interface BaseType<TType extends BaseTypes = 'dataprop'> {
name: string;
url: string;
type: TType; 
properties?: DiscriminatorType   
}
interface ObjProp extends BaseType<'objprop'>{
objPropSource: string;
}
type DiscriminatorType = BaseType | ObjProp
const root: DiscriminatorType = {
name:'name',
type: 'dataprop',
url:'string',
properties: {
name:'name2',
type:'objprop',
objPropSource:'sdf',
url:'str',        
}
}

最新更新