json-forms icon indicating copy to clipboard operation
json-forms copied to clipboard

Use json-forms to generate its schemas?

Open ouyangde opened this issue 8 years ago • 1 comments

In order to ensure that json-forms can generate any form I desired, I tried to write a schema which can generate itself, but failed. Here is my schema:

{
    "$schema": "http://json-schema.org/draft-03/schema#",
    "type": "object",
    "properties": {
        "$schema": {
            "type": "string",
            "title": "schema",
            "description": "",
            "default": "http://json-schema.org/draft-03/schema#",
            "readOnly": true,
            "required": true
        },
        "type": {
            "type": "string",
            "title": "type",
            "default": "object",
            "readOnly": true
        },
        "properties": {
            "type": "object",
            "title": "properties",
            "additionalProperties": {
                "type": "object",
                "properties":  {
                    "type": {
                        "type": "string",
                        "enum": ["integer","string","array","object","boolean"]
                    },
                    "title": {
                        "type":"string"
                    },
                    "description": {
                        "type":"string"
                    },
                    "default": {
                        "dependsOn": [ "type" ]
                    },
                    "required": {
                        "type":"boolean"
                    },
                    "enum": {
                        "dependsOn": [ "type" ]
                    }
                }
            }
        }
    }
}

Here is my resolver function:

function resolver(names, data, cb) {
  var schemas = new Object();

  for(var key in data.properties) {
    var type = data.properties[key].type;
    if (type == 'integer' || type == 'string') {
      var schema = new Object();
      schema.type = type;
      schemas["$.properties[*].default"] = schema;
      var schema = new Object();
      schema.type = 'array';
      schema.items = {type:type};
      schemas["$.properties[*].enum"] = schema;
    }
    break;
  }  
  setTimeout(function(){cb(schemas)},500); // in order to show asynchrony
}  

I encounter two problems here.

  1. There is no way to distinguish instances of additionalProperties, since they are all marked by *.
  2. I add the first property, and change option to triger my resolver function, it's OK. But subsequent add will fail with Cannot read property 'type' of undefined

ouyangde avatar Jul 21 '17 05:07 ouyangde

It can't be done this way. Think the resolver as a way of getting from a valid JSON schema to an other, depending on the actual value of the JSON instance. So the problem here is that there is no a valid JSON schema that can describe these different types per additional property.

What you can do is refactor your schema to get a conceptually equivalent schema, like for example:

  • Using pattern properties (one per each type)
  • Or using a different object (with additional properties) per type.

Since this schemas would generate JSON instances with a structure different than your actual one, and in the case you would need to maintain the actual one, you could easily perform a transformation in javascript from the generated data.

idelvall avatar Jul 21 '17 14:07 idelvall