user3587174
user3587174

Reputation: 701

Generate JSON schema from Java class

I have a POJO class:

public class Stock {
 int id;
 String name;
 Date date;
}

Are there any annotations or development framework/API that can convert POJO to JSON schema like below:

{"id":
      {             
        "type" : "int"
      },
"name":{   
        "type" : "string"
       }
"date":{
        "type" : "Date"
      }
}

And also I can expand the schema to add information like "Required" : "Yes", description for each field, etc., by specifying some annotations or configurations on POJO and can generate JSON Schema like below:

{"id":
      {             
        "type" : "int",
        "Required" : "Yes",
        "format" : "id must not be greater than 99999",
        "description" : "id of the stock"
      },
"name":{   
        "type" : "string",
        "Required" : "Yes",
        "format" : "name must not be empty and must be 15-30 characters length",
        "description" : "name of the stock"
       }
"date":{
        "type" : "Date",
        "Required" : "Yes",
        "format" : "must be in EST format",
        "description" : "filing date of the stock"
      }
}

Upvotes: 61

Views: 126733

Answers (5)

nomadus
nomadus

Reputation: 909

If you are looking for a custom solution, here is one.

 public static String generateSchema(Class currentClass) {
    StringBuilder schema = new StringBuilder();
    schema.append("{\n");
    buildProperties(currentClass, schema);
    schema.append("}");
    return schema.toString();
}

 private static void buildProperties(Class<?> clazz, StringBuilder schema) {
    for (Field field : clazz.getDeclaredFields()) {
        String fieldName = field.getName();
        field.setAccessible(true);

        if ("object".equals(getFieldType(field.getType()))) {
            if (field.isAnnotationPresent(JsonIncludeProperties.class)) {
                String[] includedProps = field.getAnnotation(JsonIncludeProperties.class).value();
                schema.append("    \"" + fieldName + "\": {\n");
                for (String prop : includedProps) {
                    Optional<Field> innerField = null;
                    if (!field.getType().isPrimitive()) {
                        innerField = Arrays.stream(field.getType().getDeclaredFields())
                                .filter(item -> item.getName().equals(prop))
                                .findFirst();
                    }

                    if (innerField.isPresent()) {
                        schema.append("      \"" + prop + "\":");
                        schema.append("\"" + getFieldType(innerField.get().getType()) + "\"\n"); // Add placeholder for definition
                    }
                }
                schema.append("    },\n");
            } else {
                schema.append("    \"" + fieldName + "\": {\n");
                for (Field innerField : field.getType().getDeclaredFields()) {
                    if (isPrimitive(innerField)) {
                        schema.append("      \"" + innerField.getName() + "\":");
                        schema.append("\"" + getFieldType(innerField.getType()) + "\"\n");
                    }
                }
                schema.append("    },\n");
            }
        } else if ("set".equals(getFieldType(field.getType()))) {
            Type genericType = field.getGenericType();

            if (genericType instanceof ParameterizedType) {
                ParameterizedType parameterizedType = (ParameterizedType) genericType;
                Type[] actualTypeArguments = parameterizedType.getActualTypeArguments();
                if (actualTypeArguments.length == 1 && actualTypeArguments[0] instanceof Class) {
                    Class<?> elementType = (Class<?>) actualTypeArguments[0];

                    schema.append("    \"" + fieldName + "\": [\n");
                    for (Field innerField : elementType.getDeclaredFields()) {
                        if (isPrimitive(innerField)) {
                            schema.append("      \"" + innerField.getName() + "\":");
                            schema.append("\"" + getFieldType(innerField.getType()) + "\"\n");
                        }
                    }
                    schema.append("    ],\n");
                }
            }
        } else {
            schema.append("  \"" + fieldName + "\": \"" + getFieldType(field.getType()) + "\",\n");
        }
    }
}

 private static String getFieldType(Class<?> type) {
    if (type.isPrimitive()) {
        if (type.equals(int.class) || type.equals(Integer.class)) {
            return "integer";
        } else if (type.equals(long.class) || type.equals(Long.class)) {
            return "number";  // Can be "integer" depending on schema needs
        } else if (type.equals(boolean.class) || type.equals(Boolean.class)) {
            return "boolean";
        } else if (type.equals(float.class) || type.equals(Float.class) ||
                type.equals(double.class) || type.equals(Double.class)) {
            return "number";
        } else {
            return "string";
        }
    } else if (type.equals(String.class)) {
        return "string";
    } else if (type.equals(Integer.class)) {
        return "integer";
    } else if (type.equals(Long.class)) {
        return "long";
    } else if (type.equals(UUID.class)) {
        return "UUID";
    } else if (type.isArray()) {
        return "array";
    } else if (Collection.class.isAssignableFrom(type)) {
        return "set";
    } else {
        return "object";
    }
}

Upvotes: 0

StaxMan
StaxMan

Reputation: 116512

EDIT: as pointed out by commenters, module is being deprecated, not maintained. So, Caveat Emptor etc


One such tool is Jackson JSON Schema module:

https://github.com/FasterXML/jackson-module-jsonSchema

which uses Jackson databind's POJO introspection to traverse POJO properties, taking into account Jackson annotations, and produces a JSON Schema object, which may then be serialized as JSON or used for other purposes.

Upvotes: 15

Edgar Domingues
Edgar Domingues

Reputation: 990

Java JSON Schema Generator: https://github.com/victools/jsonschema-generator

Creates JSON Schema (Draft 6, Draft 7 or Draft 2019-09) from Java classes using Jackson.

Upvotes: 16

P Rajesh
P Rajesh

Reputation: 401

public static String getJsonSchema(Class clazz) throws IOException {
         Field[] fields = clazz.getDeclaredFields();
         List<Map<String,String>> map=new ArrayList<Map<String,String>>();
         for (Field field : fields) {
             HashMap<String, String> objMap=new  HashMap<String, String>();
             objMap.put("name", field.getName());
             objMap.put("type", field.getType().getSimpleName());
             objMap.put("format", "");
             map.add(objMap);
         }
         ObjectMapper mapper = new ObjectMapper();
         String json = mapper.writeValueAsString(map);

       return json;
    }

Upvotes: 2

Drona
Drona

Reputation: 7234

Use JJschema. It can generate draft 4 compliant JSON schemas. Refer this post http://wilddiary.com/generate-json-schema-from-java-class/ for details.

Though Jackson Json Schema module can too generate schema but it can, as of today, only generate draft 3 compliant schemas only.

Upvotes: 2

Related Questions