javascriptjsonangularangular-formly

How can we create JSON schema to build a angular formly based forms on basis of plain JSON?


We have a requirement in which we are planning to build a form according to the JSON received and convert it to JSON schema which is supported by formlyJsonschema, is there any way of achieving this?

Eg JSON:

{
 "isSignInRequired": true,
 "isEmployee": false,
 "noOfEmployees": {
 "minValue": 3,
 "maxValue": 50
 }
}

Requirement: If the value is a boolean convert to a type of toggle and if there is an integer or string value convert to a type of textbox

Desired converted JSON Schema supported by formlyJsonschema is as follows:

"schema" :[
{
 "properties": {
 "isSignInRequired": {
 "type": "toggle",
 "default": true
 },
 "isEmployee": {
 "type": "toggle",
 "default": true
 }
}
},
{
"description": "noOfEmployees",
"type": "object",
"properties": {
"minValue": {
"type": "integer",
"title": "minValue"
},
"maxValue": {
"type": "integer",
"title": "maxValue",
"minLength": 3
}
}
}]

I tried using some JSON schema-based examples but was not able to fit my requirement into it, example is as follows:

Stackblitz Demo


Solution

  • The default and maxLength assertions are impossible to derive from one sample of data, but you can assume type and properties. There may be other assertions that you may choose to assume, such as additionalProperties.

    var data = {
        "isSignInRequired": true,
        "isEmployee": false,
        "noOfEmployees": {
            "minValue": 3,
            "maxValue": 50
        }
    };
    
    // could use lodash mapValues instead
    var mapValues = (fn, data) => Object.keys(data).reduce((accum, key) => ({ ...accum, [key]: fn(data[key], key) }), {});
    
    var toSchemaType = data =>
        Array.isArray(data)
            ? 'array'
            : typeof data;
    
    var deriveSchema = (data, key) => ({
        type: toSchemaType(data),
        ...(key && { title: key }),
        ...(toSchemaType(data) === 'object' && {
            properties: mapValues(deriveSchema, data)
        })
    });
    
    deriveSchema(data)