I am trying to adapt a product's ontology with its properties using JSON. The below mentioned JSON structure is what I am thinking about.
Each Product (Concept) has two types of properties: 1. Data Properties 2. Object Properties
Typical Definitions for these properties when using Protege is as followsSO Thread:
In Protégé there are are different tabs for creating Object Properties and Datatype Properties. If a property should relate individuals to individuals, then it needs to be an object property, and if it relates individuals to literals, then it needs to be a datatype property.
I think of every property to have the following attributes:
name: string
url: string
type: dataprop or objprop
objPropSource: available only for Objproperties
I have drawn up a small recursive JSON as below:
{
"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"
}
]
}
]
}
In a way structure provides a Binary Tree for a chair which has height
, width
etc. as dataproperties and horizontalsurface
and legislation
as objectproperties
I used the JSON to TS Online Converter to see how will the JSON be converted to Typescript Interfaces and the outcome is following:
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;
}
I infer that the aprroach for using Interfaces from Recursive JSON is not scalable since such an Ontology of a Product can scale upto 1000's of properties and properties within properties. As above mentioned example show that for every Property within a parent property would keep creating interfaces.
Should I expect to use Typescript Interfaces with such JSON structure or should to stick to creating a Class and then following the conventional method of creating a Binary Tree viz.
export class leaf {
name: string;
url: string;
type: string;
children: leaf[] = [];
}
and then writing a recursion till the complete structure is parsed?
Can Typescript interfaces be used for Large Recursive JSON Structures?
You should be able to represent that structure just fine as a recursive interface:
interface Property {
name: string;
url: string;
type: string;
objPropSource?: string;
properties?: Property[];
}
It appears that the JSON to TS converter you tried to use just doesn't have the functionality to recognize the recursive nature of your structure.
Working example:
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"
}
]
}
]
}`;
}
Two possible helpers for you, to make it easier in future.
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]
}
Disciminator Types:
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',
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With