Thursday 8 April 2021

Generate json schema from json string

 

Generating json schema from a json string is not straight forward.

 

Approach 1: Get the POJOs from json document and use JsonSchemaGenerator to generate json schema from the POJO class.

 

How to generate POJOs from json document?

Refer this post.


 

How to generate JSON schema from POJO class?

Refer my previous post.

 

 

Approach 2:  Write a parser and generate json schema document.

 

JsonSchemaWriter.java

package com.sample.app.util;

import java.io.IOException;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;

import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.node.JsonNodeType;
import com.fasterxml.jackson.databind.node.ObjectNode;


public class JsonSchemaWriter {

	private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();

	private static String getJsonSchema(JsonNode properties) throws JsonProcessingException {
		ObjectNode schema = OBJECT_MAPPER.createObjectNode();
		schema.put("type", "object");

		schema.set("properties", properties);

		ObjectMapper jacksonObjectMapper = new ObjectMapper();
		String schemaString = jacksonObjectMapper.writerWithDefaultPrettyPrinter().writeValueAsString(schema);
		return schemaString;
	}

	private static ObjectNode createProperty(JsonNode jsonData) throws IOException {
		ObjectNode propObject = OBJECT_MAPPER.createObjectNode();

		Iterator<Entry<String, JsonNode>> fieldsIterator = jsonData.fields();

		while (fieldsIterator.hasNext()) {
			Entry<String, JsonNode> field = fieldsIterator.next();

			String fieldName = field.getKey();
			JsonNode fieldValue = field.getValue();
			JsonNodeType fieldType = fieldValue.getNodeType();

			ObjectNode property = processJsonField(fieldValue, fieldType, fieldName);
			if (!property.isEmpty()) {
				propObject.set(fieldName, property);
			}
		}
		return propObject;
	}

	private static ObjectNode processJsonField(JsonNode fieldValue, JsonNodeType fieldType, String fieldName)
			throws IOException {
		ObjectNode property = OBJECT_MAPPER.createObjectNode();

		switch (fieldType) {

		case ARRAY:
			property.put("type", "array");

			if (fieldValue.isEmpty()) {
				break;
			}

			// Get first element of the array
			JsonNodeType typeOfArrayElements = fieldValue.get(0).getNodeType();
			if (typeOfArrayElements.equals(JsonNodeType.OBJECT)) {
				property.set("items", createProperty(fieldValue.get(0)));
			} else {
				property.set("items", processJsonField(fieldValue.get(0), typeOfArrayElements, fieldName));
			}

			break;
		case BOOLEAN:
			property.put("type", "boolean");
			break;

		case NUMBER:
			property.put("type", "number");
			break;

		case OBJECT:
			property.put("type", "object");
			property.set("properties", createProperty(fieldValue));
			break;

		case STRING:
			property.put("type", "string");
			break;
		default:
			break;
		}
		return property;
	}

	public static String getJsonSchema(String jsonDocument) throws IllegalArgumentException, IOException {
		Map<String, Object> map = OBJECT_MAPPER.readValue(jsonDocument, new TypeReference<Map<String, Object>>() {});
		return getJsonSchema(map);
	}

	public static String getJsonSchema(Map<String, Object> jsonDocument) throws IllegalArgumentException, IOException {

		JsonNode properties = createProperty(OBJECT_MAPPER.convertValue(jsonDocument, JsonNode.class));
		return getJsonSchema(properties);

	}

}

App.java

package com.sample.app;

import java.io.IOException;

import com.github.fge.jsonschema.core.exceptions.ProcessingException;
import com.sample.app.util.JsonSchemaWriter;

public class App {

  public static void main(String args[]) throws IllegalArgumentException, IOException, ProcessingException {

    String jsonPayload = "{\"id\":1,\"name\":\"Krishna\",\"age\":23,\"address\":{\"street\":\"Chowdeswari\",\"city\":\"Bangalore\",\"country\":\"India\"}}";

    String jsonSchema = JsonSchemaWriter.getJsonSchema(jsonPayload);
    
    System.out.println(jsonSchema);

  }

}


Output

{
  "type" : "object",
  "properties" : {
    "id" : {
      "type" : "number"
    },
    "name" : {
      "type" : "string"
    },
    "age" : {
      "type" : "number"
    },
    "address" : {
      "type" : "object",
      "properties" : {
        "street" : {
          "type" : "string"
        },
        "city" : {
          "type" : "string"
        },
        "country" : {
          "type" : "string"
        }
      }
    }
  }
}






 

 

Previous                                                    Next                                                    Home

No comments:

Post a Comment