How to create JSON Schema for Name/Value structure? - java

My problem is that i am serializing the content of map to JSON.
In the output (JSON), i have object that follow key/name syntax rule.
The key is created from map key, and the name from the value.
Model Example:
class Storage {
Map<String,String> values = new HashMap<>();
{
map.put("key1","key1");
map.put("key2","key2");
map.put("key3","key3");
}
}
JSON Example object:
{
key1=value1,
key2=value2,
key3=value3
}
JSON Schema:
{
"name": "storage",
"description": "Store of key values",
"properties": {
// How can we describe the properties if we do not know the name ?
}
}
The issue is that i do not know what the values will be but i know that they will be some.
Can you help me to provide me the full definition of schema?
Disclaimer:
I know that this can be also serialized as
{
values: [
{key="key1", value="value1"},
{key="key2", value="value2"},
{key="key3", value="value3"}
]
}
but is do not want to have array in the JSON.

Assuming your validator supports it you can use patternProperties.
For the schema...
{
"title": "Map<String,String>",
"type": "object",
"patternProperties": {
".{1,}": { "type": "string" }
}
}
...and the document...
{
"foo":"bar",
"baz":1
}
...the value of property foo is valid because it is a string but baz fails validation because it is a number.

I used the Solution suggested by #augurar
"additionalProperties": { "type": "string" }
for AWS API Gateway Model .... and the SDK was able to generate the Map variable as required in Java / Android SDK
#Arne Burmeister - in my case - Solution 1 didnt worked as needed - although it didnt gave any error in the Model (Schema Created)

Related

how to resolve all references for a JSON schema in java

I have a JSON schema , which has field like
$schema
$id
$ref
$merge
ex
{
**"$schema"**: "http://json-schema.org/draft-07/schema#",
**"$id"**: "./field_name_1.json",
"field_name_title": "some-title",
"field_name_2": "some value",
"field_name_3": {
"field_name_4": {
"field_name_5": "some value",
"field_name_6": "some value",
"field_name_7": {
"field_name_8": {
"field_name_9": "some value",
**"$ref"**: "/json_file_1.json"
},
"field_name_": {
**"$ref"**: "/json_file_2.json"
}
},
"field_name_10": false
}
},
"field_name_11": "some value",
"field_name_12": "some value",
"field_name_13": {
"field_name_14": {
**"$ref"**: "/json_file_3.json"
},
"session_data": {
**"$ref"**: "/json_file_4.json"
},
"event_payload": {
**"$ref"**: "#/field_name_3/field_name_4"
}
},
"field_name_15": false
}
how to resolve all references in the schema , and make a complete JSON.
Main goal is to map the resolved schema in to an entity and perform crud operation for schemas
There are various ways to approach this task, i.e. implement as simple automation to replace tokens on your behalf that will perform following steps:
Create a map (Map, HashMap) that will have token - value pairs
Read json via json library; that's an example how to do it - https://www.baeldung.com/java-org-json
Iterate through json and replace a token via replace method of java string.
Another approach is to do a replacement via external tools such as gradle that has a dedicated plugin for that. There are a bunch of plugins that can do that in gradle repository - https://plugins.gradle.org/search?term=token+replacement, for example this one https://github.com/HexoMod-tools/gradle.replace.token.preprocessor.plugin
Refer: java-json-tools, project.
The com.github.fge.jsonschema.core.load.RefResolver class seems to have the functionality.
Refer: javadoc
I have not tried it yet, so cannot add more information.

How to get Json key value for unkown json object structure

I have an array of JSON objects but its structure is unknown.i have struck
with how to get the value and based on value i need to generate code
"memberjson": [{
"company": {
"employee": {
"software": {
"employeetype": "permanent"
},
"type1": "401",
"type2": "541"
}
}
}, {
"trust": {
"people": {
"contract": {
"type": "available"
},
"type4": "4541",
"type5": "58771"
}
}
}]
}
How to get the value however I can request to give the path Example
JSON path 1: company.employee.software.employeetype
JSON path 2: trust.people.contract.type^trust.people.type4^trust.people.contract.type4
Based on the path I need to get the value.
in which format I need to store path so that I can get the value easily or please suggest me is there any other way to get the value for the unknown structure
Also, I need to generate code from above JSON:
Ex:
For JSON path 1: company.employee.software.employeetype^employee.company.type1^
^employee.company.type2
"generatedkey"=company.employee.software.employeetype+employee.company.type1+employee.company.type2
Final Ans:
"generatedkey":"permanent401541"
JSON path 2: trust.people.contract.type^trust.people.type4^trust.people.contract.type4
"generatedkey"=trust.people.contract.type+trust.people.type4+trust.people.contract.type4
Final Ans:
"generatedkey":"available454158771"
I tried to iterate based on a path
There is a library called JSON Path https://www.npmjs.com/package/jsonpath, here you write regular expression for the path to get the value
To test use this online tool called json path evaluator https://jsonpath.com/ to verify your path

Trim redundant attributes in json objects using java

I would like to trim the below json object. That is a json object I built on top of what mongoDB responded. What I want to do is to remove just $oid because they are redundant attributes and keep the value inside (_id or $id ) without Curley braces and simply call the attribute id.
so what I need is just "id": "2283cef627ff2cc33ad5990"
Could you please help me I am struggling with json.
{
"_id": {
"$oid": "22383cef627ff2cc33ad5990"
},
"name": "data1",
"users": [
{
"$ref": "user",
"$id": {
"$oid": "16a5fbcee4b0c2c2da3017ef"
}
},
{
"$ref": "user",
"$id": {
"$oid": "1795ff86e4b09fc66416cd2f"
}
},
],
},
a) You can use a mapper to convert your JSON to an object and then call the desired attribute, like Jackson:
ObjectMapper mapper = new ObjectMapper();
String jsonInString = YOUR_STRING;
//from String to MyClass
MyClass object = mapper.readValue(jsonInString, MyClass.class);
In this example you have to define a class MyClass with all the attributes you need (e.g. _id, name, users, etc).
b) If you want to implement a quicker solution you can manipulate directly the string; if you know that the oid is always 24 characters you can do something like
String c = str.substring(str.indexOf("\"", str.indexOf("$oid")+6)+1, str.indexOf("\"", str.indexOf("$oid")+6)+25);
but I highly recommend to take a look to Jackson and give it a try. A solution like this is very fragile and every change in the JSON will lead to a wrong result.

How to read a specific unique json attribute in jackson

This is a json of an api. my query only asks for one language (here "en") so there is only one value in the json. And this is the only thing i want to read in the json. So i think i doesnt make sense to convert it to an object. I thought of something like:
JsonNode root = mapper.readTree(genreJson); ...
But how do i get the value without knowing the name of the attribute (in the example "12345"). This is an Id i dont have.
What do you think?
{
"entities":
{
"12345":
{
"id": "12345",
"type": "item",
"descriptions":
{
"en":
{
"language": "en",
"value": "the_value_i_want"
}
}
}
},
"success": 1
}
i thought something like
JsonNode root = mapper.readTree(genreJson); ...
try this.. may work
JsonNode value = root.path("entities").path("12345").path("descriptions").path("en").path("value");
I am not sure if its an efficient approach though

Update nested field in an index of ElasticSearch with Java API

I am using Java API for CRUD operation on elasticsearch.
I have an typewith a nested field and I want to update this field.
Here is my mapping for the type:
"enduser": {
"properties": {
"location": {
"type": "nested",
"properties":{
"point":{"type":"geo_point"}
}
}
}
}
Of course my enduser type will have other parameters.
Now I want to add this document in my nested field:
"location":{
"name": "London",
"point": "44.5, 5.2"
}
I was searching in documentation on how to update nested document but I couldn't find anything. For example I have in a string the previous JSON obect (let's call this string json). I tried the following code but seems to not working:
params.put("location", json);
client.prepareUpdate(index, ElasticSearchConstants.TYPE_END_USER,id).setScript("ctx._source.location = location").setScriptParams(params).execute().actionGet();
I have got a parsing error from elasticsearch. Anyone knows what I am doing wrong ?
You don't need the script, just update it.
UpdateRequestBuilder br = client.prepareUpdate("index", "enduser", "1");
br.setDoc("{\"location\":{ \"name\": \"london\", \"point\": \"44.5,5.2\" }}".getBytes());
br.execute();
I tried to recreate your situation and i solved it by using an other way the .setScript method.
Your updating request now would looks like :
client.prepareUpdate(index, ElasticSearchConstants.TYPE_END_USER,id).setScript("ctx._source.location =" + json).execute().actionGet()
Hope it will help you.
I am not sure which ES version you were using, but the below solution worked perfectly for me on 2.2.0. I had to store information about named entities for news articles. I guess if you wish to have multiple locations in your case, it would also suit you.
This is the nested object I wanted to update:
"entities" : [
{
"disambiguated" : {
"entitySubTypes" : [],
"disambiguatedName" : "NameX"
},
"frequency" : 1,
"entityType" : "Organization",
"quotations" : ["...", "..."],
"name" : "entityX"
},
{
"disambiguated" : {
"entitySubType" : ["a", "b" ],
"disambiguatedName" : "NameQ"
},
"frequency" : 5,
"entityType" : "secondTypeTest",
"quotations" : [ "...", "..."],
"name" : "entityY"
}
],
and this is the code:
UpdateRequest updateRequest = new UpdateRequest();
updateRequest.index(indexName);
updateRequest.type(mappingName);
updateRequest.id(url); // docID is a url
XContentBuilder jb = XContentFactory.jsonBuilder();
jb.startObject(); // article
jb.startArray("entities"); // multiple entities
for ( /*each namedEntity*/) {
jb.startObject() // entity
.field("name", name)
.field("frequency",n)
.field("entityType", entityType)
.startObject("disambiguated") // disambiguation
.field("disambiguatedName", disambiguatedNameStr)
.field("entitySubTypes", entitySubTypeArray) // multi value field
.endObject() // disambiguation
.field("quotations", quotationsArray) // multi value field
.endObject(); // entity
}
jb.endArray(); // array of nested objects
b.endObject(); // article
updateRequest.doc(jb);
Blblblblblblbl's answer couldn't work for me atm, because scripts are not enabled in our server. I didn't try Bask's answer yet - Alcanzar's gave me a hard time, because I supposedly couldn't formulate the json string correctly that setDoc receives. I was constantly getting errors that either I am using objects instead of fields or vice versa. I also tried wrapping the json string with doc{} as indicated here, but I didn't manage to make it work. As you mentioned it is difficult to understand how to formulate a curl statement at ES's java API.
A simple way to update the arraylist and object value using Java API.
UpdateResponse update = client.prepareUpdate("indexname","type",""+id)
.addScriptParam("param1", arrayvalue)
.addScriptParam("param2", objectvalue)
.setScript("ctx._source.field1=param1;ctx._source.field2=param2").execute()
.actionGet();
arrayvalue-[
{
"text": "stackoverflow",
"datetime": "2010-07-27T05:41:52.763Z",
"obj1": {
"id": 1,
"email": "sa#gmail.com",
"name": "bass"
},
"id": 1,
}
object value -
"obj1": {
"id": 1,
"email": "sa#gmail.com",
"name": "bass"
}

Categories