Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I define the sequence of properties in JSON Schema?

I have following java Object:

ProcessBean.java

import java.util.List;
import com.fasterxml.jackson.annotation.JsonRootName;

@JsonRootName(value = "process")
public class ProcessBean{
    private Integer id;
    private String name;
    private String description;
    private String user;
    private String executePermissions;
    private String createdDtm;
    private String updatedDtm;
    private Process tpProcess;
    private List<ProcessParamBean> processParameters;

    /* --------Getters and Setters ----------*/
}

I need to find the JSON schema for this object which is used to display these fields on UI. The order of fields in UI is determined by the order of properties in JSON schema generated.

I have generated the schema using following code:

DataSpec.java

import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.module.jsonSchema.JsonSchema;
import com.fasterxml.jackson.module.jsonSchema.factories.SchemaFactoryWrapper;

public class DataSpec {
    public static <T> String getDataSpec(Class<T> clazz) {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
        SchemaFactoryWrapper visitor = new SchemaFactoryWrapper();
        MetauiVisitorContext obj = new MetauiVisitorContext();
        visitor.setVisitorContext(obj);
        try {
            mapper.acceptJsonFormatVisitor(clazz, visitor);
            JsonSchema schema = visitor.finalSchema();
            return mapper.writeValueAsString(schema);
        } catch (JsonProcessingException e) {
            e.printStackTrace();
            return null;
        }
    }
}

MetauiVisitorContext.java

import com.fasterxml.jackson.databind.JavaType;
import com.fasterxml.jackson.module.jsonSchema.factories.VisitorContext;

public class MetauiVisitorContext extends VisitorContext{
    @Override
    public String getSeenSchemaUri(JavaType aSeenSchema) {
        return null;
    }
}

The resultant schema looks like below:

{
  "type": "object",
  "id": "urn:jsonschema:com:restservices:api:jsonbeans:ProcessBean",
  "properties": {
    "updatedDtm": {
      "type": "string"
    },
    "createdDtm": {
      "type": "string"
    },
    "name": {
      "type": "string"
    },
    "tpProcess": {
      "type": "object",
      "id": "urn:jsonschema:com:restservices:api:jsonbeans:Process",
      "properties": {
        "name": {
          "type": "string"
        },
        "id": {
          "type": "integer"
        }
      }
    },
    "description": {
      "type": "string"
    },
    "id": {
      "type": "integer"
    },
    "processParameters": {
      "type": "array",
      "items": {
        "type": "object",
        "id": "urn:jsonschema:com:restservices:api:jsonbeans:ProcessParamBean",
        "properties": {
          "updatedDtm": {
            "type": "string"
          },
          "defaultValue": {
            "type": "string"
          },
          "createdDtm": {
            "type": "string"
          },
          "masterParam": {
            "type": "object",
            "id": "urn:jsonschema:com:restservices:api:jsonbeans:MasterParamBean",
            "properties": {
              "updatedDtm": {
                "type": "string"
              },
              "createdDtm": {
                "type": "string"
              },
              "name": {
                "type": "string"
              },
              "description": {
                "type": "string"
              },
              "id": {
                "type": "integer"
              }
            }
          },
          "name": {
            "type": "string"
          },
          "description": {
            "type": "string"
          },
          "processParamId": {
            "type": "integer"
          },
          "id": {
             "type": "integer"
          },
          "userPrompted": {
             "type": "boolean"
          },
          "tags": {
            "type": "string"
          }
        }
      }
    },
    "executePermissions": {
      "type": "string"
    },
    "user": {
      "type": "string"
    }
  }
}

As it can be seen that the order of properties in JSON schema does not match the order of fields defined in Java object which is necessary in my case.

So how can I determine the sequence of the properties?

like image 883
Niharika G. Avatar asked Jul 29 '15 04:07

Niharika G.


People also ask

What are properties in JSON?

A JSON object contains zero, one, or more key-value pairs, also called properties. The object is surrounded by curly braces {} . Every key-value pair is separated by a comma. The order of the key-value pair is irrelevant.

How do you make a property required in JSON Schema?

Required Properties By default, the properties defined by the properties keyword are not required. However, one can provide a list of required properties using the required keyword. The required keyword takes an array of zero or more strings. Each of these strings must be unique.

Does order matter in JSON Schema?

The JSON specification clearly states that the order of members in a JSON Object is of no importance; however, in many cases, such an order is important.


2 Answers

There is not an intrinsic order of properties in a JSON schema object, as it happens with a regular JSON or javascript object. Indeed, it does not change the validation semantics. The following schemas validate exactly the same collection of objects:

Schema 1:

{
    "properties" : {
        "prop1" : {
            "type" : "string"
        },
        "prop2" : {
            "type" : "number"
        }
    }
}

Schema 2:

{
    "properties" : {
        "prop2" : {
            "type" : "number"
        },
        "prop1" : {
            "type" : "string"
        }
    }
}

If you want to preserve some ordering you need to do it within and array. You could achieve this by using an array of objects instead of an object in the items clause. An example:

{
    "type" : "array" :
    "items" : [{
            "properties" : {
                "prop2" : {
                    "type" : "number"
                }
            }
        }, {
            "properties" : {
                "prop1" : {
                    "type" : "string"
                }
            }
        }
    ]
}

This way you get an ordered definition of UI items. Unfortunately, it forces you to nest each single property in an object.

like image 135
jruizaranguren Avatar answered Sep 19 '22 21:09

jruizaranguren


Order is out of scope for json-schema. For that you need to look into json-forms https://jsonforms.io/, standards, which is extension of json-schema. It consist of three separate JSON data :

  1. schema
  2. values
  3. ui-schema

The ui-schema contains the information about the ui and presentation, like order of properties (fields) and the their visual presentation, like "hidden", "read-only".

like image 22
user3852017 Avatar answered Sep 22 '22 21:09

user3852017