在使用递归JSON时,如何使用TypeScript接口

5
我正在尝试使用JSON来适应产品的本体及其属性。以下是我考虑中的JSON结构。
每个产品(概念)都有两种类型的属性:1.数据属性 2.对象属性
在使用Protege时,这些属性的典型定义如下:
根据SO线程:https://dev59.com/1mMm5IYBdhLWcg3wTtfi,在Protege中,创建对象属性和数据类型属性有不同的选项卡。如果一个属性需要将个体与个体关联起来,则它必须是一个对象属性;如果它将个体与文本字面量关联起来,则它需要是一个数据类型属性。
我认为每个属性都有以下属性:
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"
        }
        ]
    }
  ]
}

在某种程度上,结构为椅子提供了一个二叉树,其中具有“高度”、“宽度”等作为数据属性,“水平表面”和“法规”作为对象属性。

将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使用接口的方法不可扩展,因为这样一个产品的本体可以扩展到数千个属性和属性内部的属性。正如上述示例所示,对于父属性中的每个属性,都将创建接口。

期望

我应该期望在这样的JSON结构中使用TypeScript接口,还是应该坚持创建类,然后遵循创建二叉树的常规方法。

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

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

简述

Typescript接口是否可用于大型递归JSON结构?

2个回答

17

您应该可以将该结构表示为递归接口:

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"
        }
        ]
    }
  ]
}`;
}

1
@Kalle,你对我的回答所做的修改很好,但那不是我的工作。我建议你添加自己的答案并提出你的建议方法。 - JLRishe
1
除了 objPropSourceproperties 应该是接口的可选成员之外,答案很好。 - Robert Penner

1

未来可能有两个可供选择的助手,以使事情更加容易。

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',        
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接