Question:
How can I create a function that converts a dynamic Json?

Query

How can I create a function that converts a dynamic Json to a formula in JavaScript?


Problem

I need to create a method that converts a dynamic Json that has this structure


export interface Regole {

    descrizioneRegola: string;

    naturaGiuridica: string;

    regolaPerCollegamento: RegolaPerCollegamento[];

    or?: OperatoreLogico;

    and?: OperatoreLogico;

    not?: OperatoreLogico;    

}


export interface OperatoreLogico {

    regolaPerCollegamento?: RegolaPerCollegamento[];

    or?: OperatoreLogico;

    and?: OperatoreLogico;

    not?: OperatoreLogico;

}


export interface RegolaPerCollegamento {

    tipoCollegamentoEsistente?: number;

    tipoCollegamento?: number;

    quantita?: string;

    minimo?: number;

    massimo?: number;

    esattamente?: number;

}       


where the keys "or", "and", "not" can be dynamic.

For example I can have this Json in input

    

  let json: OperatoreLogico = {

          "or": {

            "and": {

              "regolaPerCollegamento": [

                {

                  "tipoCollegamentoEsistente": 115,

                  "quantita": "NESSUNO"

                },

                {

                  "tipoCollegamentoEsistente": 118,

                  "quantita": "NESSUNO"

                }

              ]

            },

            "or": {

              "regolaPerCollegamento": [

                {

                  "tipoCollegamento": 115,

                  "minimo": 1

                },

                {

                  "tipoCollegamento": 118,

                  "minimo": 1

                }

              ]

            }

          }

        }


and convert to this output:


({tipoCollegamentoEsistente: 115, quantita: "NESSUNO"} && {tipoCollegamentoEsistente: 118, quantita: "NESSUNO"}) || ({tipoCollegamento: 115, minimo: 1} || {tipoCollegamento: 115, minimo: 1})


as you can see the "and" operator in the above example needs to 'and' the two objects in array, the inner 'or' the two object in the array and the outer 'or' to concatenate the results of the inner 'and' and 'or'.


I tried to create a recursive method but it seems that doesn't work


export function convertToRule(operatoreLogico: OperatoreLogico, initial?: OperatoreLogico, 

operator?: string, result?: string): string {

  const initialJson = { ...operatoreLogico };

  if (operatoreLogico.regolaPerCollegamento) {

    const regole = Array.isArray(operatoreLogico.regolaPerCollegamento)

      ? operatoreLogico.regolaPerCollegamento

      : [operatoreLogico.regolaPerCollegamento];


    const regoleString = regole.map((regola: any) => {

      const properties = Object.keys(regola).map((key) => {

        return `"${key}": ${JSON.stringify(regola[key])}`;

      }).join(', ');

      return `{ ${properties} }`;

    }).join(operator);


    let op = Object.keys(initial!)[0];


    if (op === 'and') {

      delete initial?.and;

      result = '(' + result + ' && ' + regoleString+ ')';

      convertToRule(initial!, undefined, undefined, result + regoleString);

    } else {

      delete initial?.or;

      result = '(' + result + ' || ' + regoleString + ')';

      convertToRule(initial!, undefined, undefined, result + regoleString);

    }


    return `( ${regoleString} )`;


  } else if (operatoreLogico.and) {


    const andRules = Array.isArray(operatoreLogico.and) ? operatoreLogico.and : [operatoreLogico.and];


    andRules.map((andRule) => {

      return convertToRule(andRule, initialJson, ' && ', result);

    })

    return '';


  } else if (operatoreLogico.or) {

    const orRules = Array.isArray(operatoreLogico.or) ? operatoreLogico.or : [operatoreLogico.or];


    orRules.map((orRule) => {

      return convertToRule(orRule, initialJson, ' || ', result);

    })

    return '';

  } else {

    return '';

  }

}


Solution

This should do what you're looking for:


function compile(obj, op) {

    if (obj.regolaPerCollegamento)

        return obj.regolaPerCollegamento.map(p => JSON.stringify(p)).join(op)


    let res = []


    for (let [op, val] of Object.entries(obj)) {

        if (op === 'and')

            res.push(compile(val, ' && '))

        if (op === 'or')

            res.push(compile(val, ' || '))

        if (op === 'not')

            res.push('not ' + compile(val, ' '))

    }


    if (res.length === 1)

        return res[0]


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

}


//


let json = {

    "or": {

        "and": {

            "regolaPerCollegamento": [

                {

                    "tipoCollegamentoEsistente": 115,

                    "quantita": "NESSUNO"

                },

                {

                    "tipoCollegamentoEsistente": 118,

                    "quantita": "NESSUNO"

                }

            ]

        },

        "or": {

            "regolaPerCollegamento": [

                {

                    "tipoCollegamento": 115,

                    "minimo": 1

                },

                {

                    "tipoCollegamento": 118,

                    "minimo": 1

                }

            ]

        }

    }

}


b = compile(json, ' ')

console.log(b)


That being said, this is a weird way to represent an AST, you might be better off with a structure like this:


interface Rule { 

whatever

}


interface Node

{

    op: string

    args: Array <Node | Rule>

}


//


let ast = {

    op: 'or',

    args: [

        {

            op: 'and',

            args: [

                { "tipoCollegamentoEsistente": 115, "quantita": "NESSUNO" },

                { "tipoCollegamentoEsistente": 118, "quantita": "NESSUNO" }

            ]

        },

        {

            op: 'or',

            args: [

                { "tipoCollegamento": 115, "minimo": 1 },

                { "tipoCollegamento": 118, "minimo": 1 }

            ]

        }

    ]

}


Suggested blogs:

>How to use querySelectorAll()" with multiple conditions in JavaScript?

>How to fix mouseover event glitch in JavaScript?

>How to do light and dark mode in a website using HTML and JavaScript?

>How to manipulate manipulating Array object in JavaScript?

>How to merge an object into Array with the same key in JavaScript?

>Javascript Error Solved: Property 'id' does not exist on type 'T'

>Why highlighted table row using class not working in JavaScript?

>How to rename an object key based on the condition in JavaScript?

>How to sort an array based on another array in Javascript?

>Javascript: Modal not closing with a button


Nisha Patel

Nisha Patel

Submit
0 Answers