Guide on building a function in Typescript that transforms a dynamic Json into a formula

My task is to develop a method that can convert a dynamic Json with a specific structure

export interface Rules {
    ruleDescription: string;
    legalNature: string;
    rulesForConnection: RuleForConnection[];
    or?: LogicalOperator;
    and?: LogicalOperator;
    not?: LogicalOperator;    
}

export interface LogicalOperator {
    rulesForConnection?: RuleForConnection[];
    or?: LogicalOperator;
    and?: LogicalOperator;
    not?: LogicalOperator;
}

export interface RuleForConnection {
    existingLinkType?: number;
    linkType?: number;
    quantity?: string;
    minimum?: number;
    maximum?: number;
    exactly?: number;
}       

In this Json, the keys "or", "and", "not" are flexible.

For instance, given the following input Json:

        let json: LogicalOperator = {
          "or": {
            "and": {
              "rulesForConnection": [
                {
                  "existingLinkType": 115,
                  "quantity": "NONE"
                },
                {
                  "existingLinkType": 118,
                  "quantity": "NONE"
                }
              ]
            },
            "or": {
              "rulesForConnection": [
                {
                  "linkType": 115,
                  "minimum": 1
                },
                {
                  "linkType": 118,
                  "minimum": 1
                }
              ]
            }
          }
        }

The expected output would be:

({existingLinkType: 115, quantity: "NONE"} && {existingLinkType: 118, quantity: "NONE"}) || ({linkType: 115, minimum: 1} || {linkType: 115, minimum: 1})

In the example above, the "and" operator should combine the two objects in the array, the inner 'or' should apply to the two objects in the array, and the outer 'or' should concatenate the results of the inner 'and' and 'or'.

I have attempted to create a recursive method but it doesn't seem to be functioning as intended

export function convertToRule(logicalOperator: LogicalOperator, initial?: LogicalOperator, operator?: string, result?: string): string {
  const initialJson = { ...logicalOperator };
  if (logicalOperator.rulesForConnection) {
    // Implementation logic...
  } else if (logicalOperator.and) {
    // Implementation logic...
  } else if (logicalOperator.or) {
    // Implementation logic...
  } else {
    return '';
  }
}

Answer №1

Here is a solution that should meet your requirements:

function transform(obj, op) {
    if (obj.linkRule)
        return obj.linkRule.map(p => JSON.stringify(p)).join(op)

    let res = []

    for (let [op, val] of Object.entries(obj)) {
        if (op === 'and')
            res.push(transform(val, ' && '))
        if (op === 'or')
            res.push(transform(val, ' || '))
        if (op === 'not')
            res.push('not ' + transform(val, ' '))
    }

    if (res.length === 1)
        return res[0]

    return '(' + res.join(op) + ')'
}

//

let data = {
    "or": {
        "and": {
            "linkRule": [
                {
                    "existingLinkType": 115,
                    "quantity": "NONE"
                },
                {
                    "existingLinkType": 118,
                    "quantity": "NONE"
                }
            ]
        },
        "or": {
            "linkRule": [
                {
                    "linkType": 115,
                    "minimum": 1
                },
                {
                    "linkType": 118,
                    "minimum": 1
                }
            ]
        }
    }
}

b = transform(data, ' ')
console.log(b)

However, it's worth noting that this approach may not be the most efficient way to represent an Abstract Syntax Tree (AST). You might want to consider using a structure like this instead:

interface Rule { 
whatever
}

interface Node
{
    op: string
    args: Array <Node | Rule>
}

//

let tree = {
    op: 'or',
    args: [
        {
            op: 'and',
            args: [
                { "existingLinkType": 115, "quantity": "NONE" },
                { "existingLinkType": 118, "quantity": "NONE" }
            ]
        },
        {
            op: 'or',
            args: [
                { "linkType": 115, "minimum": 1 },
                { "linkType": 118, "minimum": 1 }
            ]
        }
    ]
}

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for integrating three-dimensional JSON models from ThreeJS into A-frame

Looking to incorporate some low poly models from into a ThreeJS JSON model in A-frame. This method is preferred due to its efficiency and smaller file size, resulting in faster loading times. However, there seems to be a lack of guidance on how to achieve ...

Having trouble with my ajax request not functioning correctly

<body style="margin:0px; padding:0px;" > <form method="post" > <input type="text" id="city" name="city" placeholder="Enter city name"> <input type="submit" value="Search City" id="searchid"/> ...

Obtaining the initial variable from an array - a simple guide

Although it seems simple, I am having trouble getting it to work. I have an array with 2 variables inside that I retrieve from jQuery. var features = [long, lat ] I want to iterate through all the values in the loop and use: fetures[i] This should give ...

In Google Chrome, the edges of hexagons appear jagged and not smooth

I have encountered an issue in Chrome where I created a hexagon group using HTML and CSS. While it displays fine in Firefox, the edges of the hexagons appear distorted in Chrome. Here are my code snippets: HTML <div class="col-sm-12 margin-left-100" i ...

How to import a 3D model with Three.js as a demonstration

I am currently working on a project that involves displaying a button labeled "Import 3d model". I want the user to be able to choose a 3ds/max/gsm 3D model to load and view on the screen. However, I am facing difficulty in implementing this functionality ...

Encountering an error message stating, "Unable to interpret property

I need to retrieve specific information import React,{Component} from 'react'; import axios from 'axios'; import CoinsConvert from '../data/data' import '../style/bootstrap.min.css'; class BoxInfo extends Component ...

Delay fading in during the loading process

Recently, I came across a neat animation effect that I would love to incorporate into an upcoming project. The effect involves animating the opacity on load, also known as a fade in. I am curious if it is possible to link multiple elements together (for ...

Choosing the parent and child elements in order to locate the specific span

I am attempting to display a telephone number when a button is clicked. While hiding the button works perfectly, I am encountering issues when trying to show the phone number by selecting the span from the currentTarget. I have attempted the following code ...

Is it possible to implement Lazy Loading exclusively on the full path in Angular 2?

Here are the paths that showcase my route configuration: calendar/2016/11/15 = Day View (DayModule) calendar/2016/11 = Month View (MonthModule) calendar/2016 = Year View (YearModule) Each view is equipped with its own Module and Components which I want ...

How can I fix the issue with Bootstrap4 input file upload not displaying the uploaded file name in the input field? Is there a way to

I am facing an issue in my Angular component where I have used a bootstrap 4 input file tag. After selecting a file, it does not display the selected file name in place of "choose file". Could someone please advise on how to show the selected file name in ...

Is it possible to remove individual items from a FlatList by clicking on them and updating the state?

I have a FlatList displaying items from an array called data. My goal is to remove each item individually by clicking on it, but currently when I click on one item, all items are deleted at once. Any suggestions on how to address this issue? Here's ...

Exploring the return type of the `within` function in TypeScript Library

I have helpers set up for my React tests using the testing library: const getSomething = (name: string, container: Screen | any = screen) { return container.getByRole('someRole', { name: name }) } The container can be either the default screen ...

The peculiar type intersection of 'string & {}'

There is a TypeScript syntax often seen in some libraries like this: type AriaRole = 'alert' | 'tree' | 'treegrid' | 'treeitem' | (string & {}); Can someone explain the meaning of string & {}? It represent ...

What is the best way to find the index of the element in an array that is closest in

I am working with an array of objects in JSON, and I need to find the index of the object in the array that has the closest number of days to a given value. Is there a built-in function in jQuery or JavaScript that can help me with this? If not, how can I ...

Creating a 3D trajectory around the Earth using a Two-Line Element Set (TLE)

I am currently working on a project to develop a 3D scene in JS/React that will visualize the orbit of the ISS around Earth. I have forked a repository from https://github.com/dsuarezv/satellite-tracker. However, I have observed that the current implement ...

Subscription to Observable content failed to run

When a submit button is clicked inside the component HTML, it triggers a function called addCollaborators(). The code for this function can be found below: component.ts emails: string[] = []; constructor(public userService: UserService) {} // Function ...

Using the `forwardRef` type in TypeScript with JSX dot notation

Currently, I am exploring the different types for Dot Notation components using forwardRef. I came across an example that showcases how dot notation is used without forwardRef: https://codesandbox.io/s/stpkm This example perfectly captures what I want to ...

What is the best way to incorporate AngularJS data into JavaScript for use in Google Chart?

How can I leverage my AngularJS scope data in a Google Chart or JavaScript? Below is my AngularJS file: angular.module('reports').controller('ReportInfoCtrl', ['$scope', 'reports', '$rootScope','$loca ...

utilize the vue component data

I have created a basic component, but I am encountering an issue where attempting to access the component's data returns undefined. Here is my code snippet: Vue.component({ template:`<div>{{message}}</div>`, data() { return { com ...

Is it feasible to create a short link for a Firebase UID?

Seeking guidance on a potential challenge that I'm facing, and I'm hoping for some expert advice. With AngularFire, I am looking to customize the uids generated on push. My goal is to create a functionality for sharing dynamic paths in Firebase, ...