I maintain a small protobuf based REST-ful API using Jersey. I am working on a small project that can call protobuf api via json proxy endpoint. To illustrate my idea, here is the list of resources and endpoints:
PersonResource
GET /getPerson -> #returns instance of PersonProto
POST /person -> create person and #returns instance of PersonProto
SubscriptionResource
GET /getSubscriptions(personId) -> #returns List<SubscriptionProto>
etc
Now using a postman like client, user can hit a protobuf request via a json proxy endpoint by passing a json request instead of protobuf message. So i d like my proxy endpoint to handle back and forth conversion between json and protobuf. Is there a reliable way to do it using Java 11 and Protocol-buffers version 3? If so could you share please some examples?
You can use reflection to access protobuf objects and create mapping between protobuf and json.
I knew we could use reflection from the beginning but I thought there may be a simpler way exist to accomplish the same. Here is the helper class that I produced for such use-case:
If you know the path to a message class or have reference to a message class somehow, then you can use JsonFormat utility of protobuf.
package com.apple.amp.commerce.support.protodive.util;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.protobuf.InvalidProtocolBufferException;
import com.google.protobuf.Message;
import com.google.protobuf.util.JsonFormat;
import java.io.UncheckedIOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class ProtoBufJsonSerializer {
private static final JsonFormat.Parser JSON_FORMAT_PARSER = JsonFormat.parser().ignoringUnknownFields();
private static final JsonFormat.Printer JSON_FORMAT_PRINTER = JsonFormat.printer().includingDefaultValueFields();
private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper();
public JsonNode getJsonNodeFromMessage(Message message) {
final String jsonString = getJsonStringMessage(message);
try {
return OBJECT_MAPPER.readTree(jsonString);
} catch (JsonProcessingException e) {
throw new UncheckedIOException(e);
}
}
private String getJsonStringMessage(Message message) {
try {
return JSON_FORMAT_PRINTER.print(message);
} catch (InvalidProtocolBufferException e) {
throw new IllegalStateException("Unable to transform message to json", e);
}
}
public Message getMessageFromJson(String messageClassName, JsonNode requestPayload) {
Message.Builder msgBuilder = getMessageBuilder(messageClassName);
try {
String jsonString = requestPayload.toString();
JSON_FORMAT_PARSER.merge(jsonString, msgBuilder);
return msgBuilder.build();
} catch (InvalidProtocolBufferException e) {
throw new IllegalStateException(e);
}
}
private Message.Builder getMessageBuilder(String messageClassName) {
try{
Class<? extends Message> msgClass = (Class<? extends Message>) Class.forName(messageClassName);
Method toBuilderMethod = msgClass.getMethod("getDefaultInstance");
Message msg = (Message) toBuilderMethod.invoke(null);
return msg.toBuilder();
} catch(IllegalAccessException | ClassNotFoundException | NoSuchMethodException | InvocationTargetException e){
throw new IllegalStateException("Unable to transform json into message", e);
}
}
}
Related
I am trying to return a list of files from a directory. Here's my code:
package com.demo.web.api.file;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.demo.core.Logger;
import io.swagger.v3.oas.annotations.Operation;
#RestController
#RequestMapping(value = "/files")
public class FileService {
private static final Logger logger = Logger.factory(FileService.class);
#Value("${file-upload-path}")
public String DIRECTORY;
#Value("${file-upload-check-subfolders}")
public boolean CHECK_SUBFOLDERS;
#GetMapping(value = "/list")
#Operation(summary = "Get list of Uploaded files")
public ResponseEntity<List<File>> list() {
List<File> files = new ArrayList<>();
if (CHECK_SUBFOLDERS) {
// Recursive check
try (Stream<Path> walk = Files.walk(Paths.get(DIRECTORY))) {
List<Path> result = walk.filter(Files::isRegularFile).collect(Collectors.toList());
for (Path p : result) {
files.add(p.toFile().getAbsoluteFile());
}
} catch (Exception e) {
logger.error(e.getMessage());
}
} else {
// Checks the root directory only.
try (Stream<Path> walk = Files.walk(Paths.get(DIRECTORY), 1)) {
List<Path> result = walk.filter(Files::isRegularFile).collect(Collectors.toList());
for (Path p : result) {
files.add(p.toFile().getAbsoluteFile());
}
} catch (Exception e) {
logger.error(e.getMessage());
}
}
return ResponseEntity.ok().body(files);
}
}
As seen in the code, I am trying to return a list of files.
However, when I test in PostMan, I get a list of string instead.
How can I make it return the file object instead of the file path string? I need to get the file attributes (size, date, etc.) to display in my view.
I would recommend that you change your ResponseEntity<> to return not a List of File but instead, a List of Resource, which you can then use to obtain the file metadata that you need.
public ResponseEntity<List<Resource>> list() {}
You can also try specifying a produces=MediaType... param in your #GetMapping annotation so as to tell the HTTP marshaller which kind of content to expect.
You'd have to Create a separate payload with the details you wanna respond with.
public class FilePayload{
private String id;
private String name;
private String size;
public static fromFile(File file){
// create FilePayload from File object here
}
}
And convert it using a mapper from your internal DTO objects to payload ones.
final List<FilePayload> payload = files.forEach(FilePayload::fromFile).collect(Collectors.toList());
return new ResponseEntity<>(payload, HttpStatus.OK);
I think you should not return a body in this case as you may be unaware of the size.
Better to have another endpoint to GET /files/{id}
I did give this another thought. What I just needed was the filename, size and date of the file. From there, I can get the file extension and make my list display look good already.
Here's the refactored method:
#GetMapping(value = "/list")
#Operation(summary = "Get list of Uploaded files")
public ResponseEntity<String> list() {
JSONObject responseObj = new JSONObject();
List<JSONObject> files = new ArrayList<>();
// If CHECK_SUBFOLDERS is true, pass MAX_VALUE to make it recursive on all
// sub-folders. Otherwise, pass 1 to use the root directory only.
try (Stream<Path> walk = Files.walk(Paths.get(DIRECTORY), CHECK_SUBFOLDERS ? MAX_VALUE : 1)) {
List<Path> result = walk.filter(Files::isRegularFile).collect(Collectors.toList());
for (Path p : result) {
JSONObject file = new JSONObject();
file.put("name", p.toFile().getName());
file.put("size", p.toFile().length());
file.put("lastModified", p.toFile().lastModified());
files.add(file);
}
responseObj.put("data", files);
} catch (Exception e) {
String errMsg = CoreUtils.formatString("%s: Error reading files from the directory: \"%s\"",
e.getClass().getName(), DIRECTORY);
logger.error(e, errMsg);
responseObj.put("errors", errMsg);
}
return ResponseEntity.ok().body(responseObj.toString());
}
The above was what I ended up doing. I created a JSONObject of the props I need, and then returned the error if it did not succeed. This made it a lot better for me.
I'm learning to create a REST Assured and Cucumber framework from scratch following a tutorial video on Youtube.
Below is the step definition and the method it calls in the RestAssuredExtension class.
#Given("^I perform GET operation for \"([^\"]*)\"$")
public void i_Perform_GET_Operation_For(String url) throws Throwable {
RestAssuredExtension.GetOps(url);
}
package utilities;
import io.restassured.RestAssured;
import io.restassured.builder.RequestSpecBuilder;
import io.restassured.http.ContentType;
import io.restassured.response.Response;
import io.restassured.response.ResponseOptions;
import io.restassured.specification.RequestSpecification;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Map;
public class RestAssuredExtension {
public static RequestSpecification Request;
public RestAssuredExtension() {
//Arrange
RequestSpecBuilder builder = new RequestSpecBuilder();
builder.setBaseUri("http://localhost:3000/");
builder.setContentType(ContentType.JSON);
var requestSpec = builder.build();
Request = RestAssured.given().spec(requestSpec);
}
public static ResponseOptions<Response> GetOps(String url) {
//Act
try {
return Request.get(new URI(url));
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
}
In the video tutorial, the test passes successfully. But when I run the test myself, it results in the following error:
Step failed
java.lang.NullPointerException: Cannot invoke "io.restassured.specification.RequestSpecification.get(java.net.URI)" because "utilities.RestAssuredExtension.Request" is null
at utilities.RestAssuredExtension.GetOps(RestAssuredExtension.java:42)
at steps.GETPostSteps.i_Perform_GET_Operation_For(GETPostSteps.java:21)
Any takers please?
From the example you have given, I think you have not initialized the RestAssuredExtension.Request field.
In the video (I quickly skimmed it), they provide a hook to create a new instance of the RestAssuredExtension before any tests are executed. This will ensure that the public static class variable Request will have been initialized to a non-null value.
My recommendation, if you want to reduce dependency for setup on the test framework and make use of static methods:
public final class RequestExtension {
private static RequestSpecification request;
// Ensure that no one is able to create an instance and thereby bypass proper initalization
private RequestExtension() {
}
// Ensures the initialization responsibility is within the class itself and not a hidden dependency for other users.
private static void getInstance() {
if (request == null) {
RequestSpecBuilder builder = new RequestSpecBuilder();
builder.setBaseUri("http://localhost:3000/");
builder.setContentType(ContentType.JSON);
var requestSpec = builder.build();
request = RestAssured.given().spec(requestSpec);
}
return request;
}
public static ResponseOptions<Response> GetOps(String url) {
// Initialize
getInstance();
// Act
try {
return request.get(new URI(url));
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
}
Otherwise, mixing static methods with dependencies on the instance will keep tripping people up. Would go either with the above or remove static from the class altogether:
public class RequestExtension {
private RequestSpecification request;
public RestAssuredExtension() {
//Arrange
RequestSpecBuilder builder = new RequestSpecBuilder();
builder.setBaseUri("http://localhost:3000/");
builder.setContentType(ContentType.JSON);
var requestSpec = builder.build();
request = RestAssured.given().spec(requestSpec);
}
public ResponseOptions<Response> GetOps(String url) {
//Act
try {
return request.get(new URI(url));
} catch (URISyntaxException e) {
e.printStackTrace();
}
return null;
}
}
One thing to help with debugging is to follow Java naming conventions. The capitalisation of your class field RequestSpecification makes it read as a class not a field name. (Request vs request) It was the same in the video so its a source issue. :)
i am using dialogflow v1
with spring boot java as webhook using:
http://mvnrepository.org/artifact/ai.api/libai/1.6.12
now i try upgrading to dialogflow v2 using this:
http://mvnrepository.org/artifact/com.google.apis/google-api-services-dialogflow/v2-rev2-1.23.0
<dependency>
<groupId>com.google.apis</groupId>
<artifactId>google-api-services-dialogflow</artifactId>
<version>v2-rev2-1.23.0</version>
</dependency>
purpose: so i dont have to take care of parsing/building the json myself
i have found it over the mvnrepository search
i intercepted this json:
{
"responseId": "72945ef4-0897-4705-a770-a12100162b45",
"queryResult": {
"queryText": "was gibts neues?",
"action": "GetNewsFromWordpress",
"parameters": {
"allRequiredParamsPresent": true
},
"name": "projects/kreamont-abf6b/agent/intents/fe2c13a1-2e3f-48eb-a15a-660501c16807",
"diagnosticInfo": {
}
},
"languageCode": {
"intentDetectionConfidence": 1.0
},
"displayName": {
"payload": {
}
},
"session": "projects/kreamont-abf6b/agent/sessions/e69aabe7-4f6a-4224-b881-8bbf31835ef2"
}
jackson is somehow unable to bind the model. how can i use some java lib so i dont have to take care of parsing the json myself?
com.fasterxml.jackson.databind.JsonMappingException: Can not set com.google.api.services.dialogflow.v2.model.GoogleCloudDialogflowV2QueryResult field com.google.api.services.dialogflow.v2.model.GoogleCloudDialogflowV2WebhookRequest.queryResult to java.util.LinkedHashMap (through reference chain: com.google.api.services.dialogflow.v2.model.GoogleCloudDialogflowV2WebhookRequest["queryResult"])
#RequestMapping(method = RequestMethod.POST, path = "fulfillment", consumes = MediaType.APPLICATION_JSON_VALUE)
public GoogleCloudDialogflowV2WebhookResponse getFulfillment(#RequestBody GoogleCloudDialogflowV2WebhookRequest request) {
// HttpMessageNotReadableException
...
The library is depending on the google-api-client. That has a customized json parser for the transfer objects (like GoogleCloudDialogflowV2WebhookRequest). These objects extending from a map. Their elements are marked with the Key annotation. That is why the normal jackson or gson parsers are failing. You have multiple options:
copy and modify the transfer objects (bad if the api will change in the future)
write a httpmessageconverter for spring that uses the google api json parser (do not know how much effort that would be)
disable the spring message converters for your endpoint and do the marshalling on your own like this:
import com.google.api.client.json.JsonGenerator;
import com.google.api.client.json.jackson2.JacksonFactory;
import com.google.api.services.dialogflow.v2.model.*;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RestController;
import reactor.core.publisher.Mono;
import java.io.IOException;
import java.io.StringWriter;
import java.util.Collections;
#RestController
public class DialogflowWebhookController {
private static JacksonFactory jacksonFactory = JacksonFactory.getDefaultInstance();
#PostMapping("/dialogflow")
public Mono<String> webhook(#RequestBody String rawRequest) throws IOException {
GoogleCloudDialogflowV2WebhookRequest request = jacksonFactory.createJsonParser(rawRequest)
.parse(GoogleCloudDialogflowV2WebhookRequest.class);
StringWriter stringWriter = new StringWriter();
JsonGenerator jsonGenerator = jacksonFactory.createJsonGenerator(stringWriter);
GoogleCloudDialogflowV2WebhookResponse response = ...
jsonGenerator.serialize(response);
jsonGenerator.flush();
return Mono.just(stringWriter.toString());
}
}
Adding to what #aheil has already mentioned.
Properties of class GoogleCloudDialogflowV2WebhookRequest is annotated with #com.google.api.client.util.Key which is why Jackson framework is unable to serialize it.
However, you can use GsonFactory which exist in com.google.api.client.json.gson package to serialize and de-serialize such classes.
This saves writing your custom parser.
#PostMapping(value = "/fulfillment", produces = {MediaType.APPLICATION_JSON_VALUE})
public GoogleCloudDialogflowV2WebhookResponse webhook(HttpServletRequest servletRequest) throws IOException {
GoogleCloudDialogflowV2WebhookRequest request = GsonFactory.getDefaultInstance().createJsonObjectParser()
.getJsonFactory()
.fromString(getRequestBody(servletRequest), GoogleCloudDialogflowV2WebhookRequest.class);
return intentFactory.handleRequest(request);
}
private String getRequestBody(HttpServletRequest request) {
try {
return new BufferedReader(new InputStreamReader(request.getInputStream()))
.lines()
.collect(Collectors.joining(System.lineSeparator()));
} catch (IOException e) {
throw new RuntimeException(e);
}
}
I am new to Java and using karate for API automation. I need help to integrate testrail with karate. I want to use tags for each scenario which will be the test case id (from testrail) and I want to push the result 'after the scenario'.
Can someone guide me on this? Code snippets would be more appreciated. Thank you!
I spent a lot of effort for this.
That's how I implement. Maybe you can follow it.
First of all, you should download the APIClient.java and APIException.java files from the link below.
TestrailApi in github
Then you need to add these files to the following path in your project.
For example: YourProjectFolder/src/main/java/testrails/
In your karate-config.js file, after each test, you can send your case tags, test results and error messages to the BaseTest.java file, which I will talk about shortly.
karate-config.js file
function fn() {
var config = {
baseUrl: 'http://111.111.1.111:11111',
};
karate.configure('afterScenario', () => {
try{
const BaseTestClass = Java.type('features.BaseTest');
BaseTestClass.sendScenarioResults(karate.scenario.failed,
karate.scenario.tags, karate.info.errorMessage);
}catch(error) {
console.log(error)
}
});
return config;
}
Please dont forget give tag to scenario in Feature file.
For example #1111
Feature: ExampleFeature
Background:
* def conf = call read('../karate-config.js')
* url conf.baseUrl
#1111
Scenario: Example
Next, create a runner file named BaseTests.java
BaseTest.java file
package features;
import com.intuit.karate.junit5.Karate;
import net.minidev.json.JSONObject;
import org.junit.jupiter.api.BeforeAll;
import testrails.APIClient;
import testrails.APIException;
import java.io.IOException;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.HashMap;
import java.util.List;
import java.util.Locale;
import java.util.Map;
public class BaseTest {
private static APIClient client = null;
private static String runID = null;
#BeforeAll
public static void beforeClass() throws Exception {
String fileName = System.getProperty("karate.options");
//Login to API
client = new APIClient("Write Your host, for example
https://yourcompanyname.testrail.io/");
client.setUser("user.name#companyname.com");
client.setPassword("password");
//Create Test Run
Map data = new HashMap();
data.put("suite_id", "Write Your Project SuitId(Only number)");
data.put("name", "Api Test Run");
data.put("description", "Karate Architect Regression Running");
JSONObject c = (JSONObject) client.sendPost("add_run/" +
TESTRAİL_PROJECT_ID, data);
runID = c.getAsString("id");
}
//Send Scenario Result to Testrail
public static void sendScenarioResults(boolean failed, List<String> tags, String errorMessage) {
try {
Map data = new HashMap();
data.put("status_id", failed ? 5 : 1);
data.put("comment", errorMessage);
client.sendPost("add_result_for_case/" + runID + "/" + tags.get(0),
data);
} catch (IOException e) {
e.printStackTrace();
} catch (APIException e) {
e.printStackTrace();
}
}
#Karate.Test
Karate ExampleFeatureRun() {
return Karate.run("ExampleFeatureRun").relativeTo(getClass());
}
}
Please look at 'hooks' documented here: https://github.com/intuit/karate#hooks
And there is an example with code over here: https://github.com/intuit/karate/blob/master/karate-demo/src/test/java/demo/hooks/hooks.feature
I'm sorry I can't help you with how to push data to testrail, but it may be as simple as an HTTP request. And guess what Karate is famous for :)
Note that values of tags can be accessed within a test, here is the doc for karate.tagValues (with link to example): https://github.com/intuit/karate#the-karate-object
Note that you need to be on the 0.7.0 version, right now 0.7.0.RC8 is available.
Edit - also see: https://stackoverflow.com/a/54527955/143475
A rest service needs to validate all incoming json data against a json schema. The json schemas are public accessible and can be retrieved via http requests.
I'm using the jackson-framwork for marshaling and unmarshaling between java and json. So far I couldn't find any possibility to validate the data against the schema by using jackson.
I also tried the JsonTools framework which obviously comes up with such a validation functionality. But unfortunately it wasn't possible for me to get the validation to work. Why JsonTool schema validation isn't working?
How can I do such a validation?
I searched for the best practice to enforce validation for incoming json data into a RESTful service. My suggestion is to use a MessageBodyReader which performs the validation inside the readFrom method. Below there is an message-body-reader example which is non-generic for the sake of simplicity.
I also was interesed in finding the best framework for doing json data validation. Because I use the jackson framework (version 1.8.5) for marshaling and unmarshaling between json and java, it would have been nice if this framework would provide a json data validation functionality. Unfortunately I couldn't find any possibility to do this with jackson. Finally I got it working with the json-schema-validator available at https://github.com. The version I use is 2.1.7
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.lang.annotation.Annotation;
import java.lang.reflect.Type;
import javax.servlet.ServletContext;
import javax.ws.rs.Consumes;
import javax.ws.rs.WebApplicationException;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.MultivaluedMap;
import javax.ws.rs.ext.MessageBodyReader;
import javax.ws.rs.ext.Provider;
import org.codehaus.jackson.map.ObjectMapper;
import at.fhj.ase.dao.data.Address;
import at.fhj.ase.xmlvalidation.msbreader.MessageBodyReaderValidationException;
import com.fasterxml.jackson.databind.JsonNode;
import com.github.fge.jackson.JsonLoader;
import com.github.fge.jsonschema.exceptions.ProcessingException;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jsonschema.main.JsonValidator;
import com.github.fge.jsonschema.report.ProcessingReport;
#Provider
#Consumes(MediaType.APPLICATION_JSON)
public class AddressJsonValidationReader implements MessageBodyReader<Address> {
private final String jsonSchemaFileAsString;
public AddressJsonValidationReader(#Context ServletContext servletContext) {
this.jsonSchemaFileAsString = servletContext
.getRealPath("/json/Address.json");
}
#Override
public boolean isReadable(Class<?> type, Type genericType,
Annotation[] annotations, MediaType mediaType) {
if (type == Address.class) {
return true;
}
return false;
}
#Override
public Address readFrom(Class<Address> type, Type genericType,
Annotation[] annotations, MediaType mediaType,
MultivaluedMap<String, String> httpHeaders, InputStream entityStream)
throws IOException, WebApplicationException {
final String jsonData = getStringFromInputStream(entityStream);
System.out.println(jsonData);
InputStream isSchema = new FileInputStream(jsonSchemaFileAsString);
String jsonSchema = getStringFromInputStream(isSchema);
/*
* Perform JSON data validation against schema
*/
validateJsonData(jsonSchema, jsonData);
/*
* Convert stream to data entity
*/
ObjectMapper m = new ObjectMapper();
Address addr = m.readValue(stringToStream(jsonData), Address.class);
return addr;
}
/**
* Validate the given JSON data against the given JSON schema
*
* #param jsonSchema
* as String
* #param jsonData
* as String
* #throws MessageBodyReaderValidationException
* in case of an error during validation process
*/
private void validateJsonData(final String jsonSchema, final String jsonData)
throws MessageBodyReaderValidationException {
try {
final JsonNode d = JsonLoader.fromString(jsonData);
final JsonNode s = JsonLoader.fromString(jsonSchema);
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
JsonValidator v = factory.getValidator();
ProcessingReport report = v.validate(s, d);
System.out.println(report);
if (!report.toString().contains("success")) {
throw new MessageBodyReaderValidationException(
report.toString());
}
} catch (IOException e) {
throw new MessageBodyReaderValidationException(
"Failed to validate json data", e);
} catch (ProcessingException e) {
throw new MessageBodyReaderValidationException(
"Failed to validate json data", e);
}
}
/**
* Taken from <a href=
* "http://www.mkyong.com/java/how-to-convert-inputstream-to-string-in-java/"
* >www.mkyong.com</a>
*
* #param is
* {#link InputStream}
* #return Stream content as String
*/
private String getStringFromInputStream(InputStream is) {
BufferedReader br = null;
StringBuilder sb = new StringBuilder();
String line;
try {
br = new BufferedReader(new InputStreamReader(is));
while ((line = br.readLine()) != null) {
sb.append(line);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (br != null) {
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return sb.toString();
}
private InputStream stringToStream(final String str) throws UnsupportedEncodingException {
return new ByteArrayInputStream(str.getBytes("UTF-8"));
}
}
import com.github.fge.jsonschema.core.report.ProcessingReport;
import com.github.fge.jsonschema.main.JsonSchema;
import com.github.fge.jsonschema.main.JsonSchemaFactory;
import com.github.fge.jackson.JsonLoader;
import com.fasterxml.jackson.databind.JsonNode;
public class ValidationJSON {
public static void main(String[] arr){
String jsonData = "{\"name\": \"prem\"}";
String jsonSchema = ""; //Schema we can generate online using http://jsonschema.net/
final JsonNode data = JsonLoader.fromString(jsonData);
final JsonNode schema = JsonLoader.fromString(jsonSchema);
final JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
JsonValidator validator = factory.getValidator();
ProcessingReport report = validator.validate(schema, data);
System.out.println(report.isSuccess());
}
}