使用带有递归 JSON 的 Typescript 接口
Posted
技术标签:
【中文标题】使用带有递归 JSON 的 Typescript 接口【英文标题】:Using Typescript Interface with a Recursive JSON 【发布时间】:2018-06-25 11:12:40 【问题描述】:我正在尝试使用 JSON 来调整产品的本体及其属性。下面提到的JSON结构是我正在考虑的。
每个产品(概念)都有两种类型的属性: 1. 数据属性 2. 对象属性
使用 Protege 时这些属性的典型定义如下SO Thread:
在 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"
]
]
在某种程度上,结构为椅子提供了一个二叉树,其中height
、width
等作为数据属性,horizontalsurface
和legislation
作为对象属性
JSON 到 Typescript 中的接口
我使用JSON to TS Online Converter 来查看如何将 JSON 转换为 Typescript 接口,结果如下:
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 中的接口的方法是不可扩展的,因为这样的产品本体可以扩展到 1000 个属性和属性中的属性。如上例所示,对于父属性中的每个属性,都会不断创建接口。
期待
我应该期望使用具有这种 JSON 结构的 Typescript 接口,还是应该坚持创建一个类,然后遵循创建二叉树的常规方法即。
export class leaf
name: string;
url: string;
type: string;
children: leaf[] = [];
然后写一个递归直到解析完整的结构?
TL;DR
Typescript 接口可以用于大型递归 JSON 结构吗?
【问题讨论】:
【参考方案1】:您应该能够将该结构很好地表示为递归接口:
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"
]
]
`;
【讨论】:
@Kalle 您对我的回答所做的编辑很好,但它们不是我的工作。我建议您使用建议的方法添加自己的答案。 除了objPropSource
和properties
之外的好答案应该是接口的可选成员。【参考方案2】:
两个可能的帮手,让您在未来更轻松。
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',
【讨论】:
以上是关于使用带有递归 JSON 的 Typescript 接口的主要内容,如果未能解决你的问题,请参考以下文章
带有 TypeScript 解析器/插件的 ESLint:如何包含从 tsconfig.json 中排除的 .spec.ts?
Typescript - 从带有日期字符串的 Json 字符串自动转换为带有 Date 属性的对象