Validate Map<String,Object> object matches json schema - java

I have a json schema, for example:
{
"type": "object",
"ignoreUnknown": true,
"properties": {
"address" : {
"type" : "string"
}
}
}
I want to check whether an object of type Map<String,Object> matches the schema or not.
The schema is received as a String.
How can I achieve this in Java? (Preferably using Jackson)
Thanks.

Although it isn't Jackson-based, you can do that using the everit-org/json-schema library as follows:
Map<String, Object> myInstance = ...
SchemaLoader.builder()
.schemaJson(new JSONObject("{my-schema-json}"))
.build().load().build().validate(new JSONObject(myInstance));
Disclaimer: I am a developer of this library

Related

How to ignore dynamic key when deserialising JSON with jackson

I am trying to access the data inside the X-Amz-Content-Sha256 parameter, but the X-Amz-Content-Sha256 key is different for each request so I cannot hardcode the key value.
Is there a way to access an object without knowing its key, when using mapper.readValue()?
"components": {
"parameters": {
"X-Amz-Content-Sha256": {
"name": "X-Amz-Content-Sha256",
"in": "header",
"schema": {
"type": "string"
},
}
}
}
You need to deserialize it to Map. Then you can check Map key to get desired values.
Sample code to deserialize JSON string to Map:
ObjectReader reader = new ObjectMapper().readerFor(Map.class);
Map<String, Object> jsonMap = reader.readValue(jsonString);

ElasticSearch Make Field non-searchable from java

I am currently working on elastic search through my java Application . I know how to index the Java pojo using RestHighLevelClient. How i can make search only on new fields not the complete pojo.?
public class Employee{
private long id;
private String name;
private String designation;
private String address; //want to index but not searchable in elastic search
}
My Code for indexing is below which is working fine:
public String saveToEs(Employee employee) throws IOException {
Map<String, Object> map = objectMapper.convertValue(employee, Map.class);
IndexRequest indexRequest =
new IndexRequest(INDEX, TYPE, employee.getId().toString()).source(map, XContentType.JSON);
IndexResponse indexResponse = client.index(indexRequest, RequestOptions.DEFAULT);
I need to do this in java .Any help please or good link ?
Writing another answer for RestHighLevelClient As another answer is useful for people not using the Rest client and adding this in the first answer makes it too long.
Note: you are passing the type which is deprecated in ES 7.X and I am using the ES 7.X version, so my code is according to 7.X.
CreateIndexRequest request = new CreateIndexRequest("employee");
Map<String, Object> name = new HashMap<>();
name.put("type", "text");
Map<String, Object> address = new HashMap<>();
address.put("type", "text");
address.put("index", false);
Map<String, Object> properties = new HashMap<>();
properties.put("name", name);
properties.put("address", address);
Map<String, Object> mapping = new HashMap<>();
mapping.put("properties", properties);
request.mapping(mapping);
CreateIndexResponse createIndexResponse = client.indices().create(request, RequestOptions.DEFAULT);
Important points
I've used only 2 fields for illustration purpose, one of which is address field which is not searchable, and to do that I used, address.put("index", false); , while name is searchable field and there this option isn't present.
I've created index mapping using the Map method which is available in this official ES doc.
you can check the mapping created by this code, using mapping REST API.
Below is the mapping generated for this code in my system and you can see, index: false is added in the address field.
{
"employee": {
"mappings": {
"properties": {
"address": {
"type": "text",
"index": false
},
"name": {
"type": "text"
}
}
}
}
}
You can just use the same search JSON mentioned in the previous answer, to test that it's not searchable.
Use the index option as false on the address field, which is by default true to make it unsearchable. As mention in the same official ES link:
The index option controls whether field values are indexed. It accepts
true or false and defaults to true. Fields that are not indexed are
not queryable.
Let me show you how can you test it using the REST API and then the java code(using rest-high level client) to accomplish it.
Mapping
{
"mappings": {
"properties": {
"id": {
"type": "long"
},
"name": {
"type": "text"
},
"designation": {
"type": "text"
},
"address": {
"type": "text",
"index" : false --> made `index` to false
}
}
}
}
Index few docs
{
"address" : "USA",
"name" : "Noshaf",
"id" : 234567892,
"designation" : "software engineer"
}
{
"address" : "USA california state",
"name" : "opster",
"id" : 234567890,
"designation" : "software engineer"
}
A simple match search query in JSON format on address field
{
"query": {
"match" : {
"address" : "USA"
}
}
}
Exception from Elasticsearch clearly mention, it's not searchable
"caused_by": {
"type": "illegal_argument_exception",
"reason": "Cannot search on field [address] since it is not indexed."
}

How to compare only structure (ignore values) of two JSON objects by jackson library?

I use library org.codehaus.jackson. I have 2 JSON object. First object I read from file hello.json. Second I generate automatically.
First:
{
"name": "some value",
"date": 1480971600000
}
Second:
{
"name": "some value",
"date": 1480971600777
}
They have the same structure but different values of "date" property. I want to compare only structure of these objects ignoring values. How can I do that?
If you have fixed set of JSON formats then easiest way would be to create JSON Schema and validate with it. Something like:
JsonNode data = JsonLoader.fromString(jsonData);
JsonNode schema = JsonLoader.fromString(jsonSchema);
JsonSchemaFactory factory = JsonSchemaFactory.byDefault();
JsonValidator validator = factory.getValidator();
ProcessingReport report = validator.validate(schema, data);

declare java.util.Map into json-schema

I need to map a java.util.Map instance into a JSON-schema that is used by org.jsonschema2pojo maven plugin to create a POJO.
I didn't find a good and simple solution for this.
Could someone help me please?
This is my actual json-schema file
{
"$schema": "http://json-schema.org/draft-04/schema#",
"title": "Response",
"description": "A Response object",
"type": "object",
"properties": {
"result": {
"type": "string",
"description": "describes response status"
},
"msg": {
"type": "string",
"description": "user msgs"
}
},
"required": ["result"],
"additionalProperties": false
}
I need to add a field "errors" that is converted into a java.util.Map<String, String> in Java.
AFAIK additionalProperties does the job.
You can declare an errors property of type Map<String, Object> for example like this (this is yaml now):
...
properties:
errors:
type: object
additionalProperties:
type: object
You don't specify the type of the keys, since this describes a json document, which naturally has strings as keys on objects.
instead of type: object you can also do type: string for Map<String, String> or reference another definition if you have your own type as values in that map.

Searching JSon string using java

I am new To JSon and i want to search the following json string and get the required output.
String:
{"status":"Success","code":"200","message":"Retrieved Successfully","reason":null,"
"projects":
[
{
"projectName": "example",
"users":
[
{
"userName": "xyz",
"executions":
[
{
"status": "check",
"runs":
[
{
"Id": "------",
"Key": "---"
}
],
"RCount": 1
}
],
"RCount": 1
}
],
"RCount": 1
},
Like that i have many projects and now , if i give projectname and username as input i wantt to get its status as output.
Is it possible?If yes how?
You may use JSONObject for this.
JSONObject json = new JSONObject(string);
JSONArray[] projectsArray = json.getJSONArray("projects");
for(int i = 0; i < projectsArray.length; ++i)
{
String projectName = projectsArray[i].getString("projectName");
...
}
Use the same method to get the users.
You can use gson library. Using gson convert your json string to Map and then you can iterate through map to get required item
Type type = new TypeToken<Map<String, Object>>(){}.getType();
Map<String, Object> myMap = gson.fromJson(jsonString, type);
You can use the Google gson to map your json data structure to a Java POJOs.
Example :
You can have Projects class containing list/array of Users.
Users class containing list/array of Executions and so on.
Gson library can easily map the json to these classes as objects and you can access your data in a more elegant manner.
Here are a few references :
http://howtodoinjava.com/2014/06/17/google-gson-tutorial-convert-java-object-to-from-json/
http://www.mkyong.com/java/how-do-convert-java-object-to-from-json-format-gson-api/

Categories

Resources