serialize String property as nested JSON object - java

I need the String property of object to be serialized as nested JSON without any escaping etc. So given json:
{
"regularProperty" : "Test here",
"nestedJSON" : {
"propertyArray" : [1,2,3],
"propertyText" : "new Text",
"anotherObject" : { ... }
}
}
And the nestedJSON property must contain the text
{
"propertyArray" : [1,2,3],
"propertyText" : "new Text",
"anotherObject" : { ... }
}
How is it possible for both serialization/deserialization? Any specific annnotation or data type?

Maybe add the annotation JsonRawValue on the nestedJSON field? I never used it before but it seems quite promising for your case.

Related

Object containing a JSON array won't parse into a JSONArray Object Java (org.json.simple)

I've been trying to access a JSON array bedded in a JSONObject (org.json.simple) to get the values or just the size of the array.
This is a simplified version of the JSON provided:
{
"paymentId" : 123,
"creditors" : [
{
"id" : 1,
"name" : "name1"
},
{
"id" : 2,
"name" : "name2"
}
]
}
In my current attempt the JSON data is stored in a JSONObject (org.json.simple) and I am trying to get the size of the "creditors"-array and the names of the creditors.
Here is what I've got so far:
public String getNumberOfTransactions(JSONObject inputData){
int numberOfTransactions = 0;
if(inputData.containsKey("creditors")){
System.out.println("inputData contains key");
Object simpleCreditorsObject = inputData.get("creditors");
if(simpleCreditorsObject instanceof JSONArray) {
System.out.println("worked");
}
}
return Integer.toString(numberOfTransactions);
}
The console logs show, that the inputData contains the key.
When console logging the simpleCreditorsObject it prints:
{"creditors":[{"id":1,"name":"name1"},{"id":2,"name":"name2"}],"paymentId":123}
When I try to just parse it:
JSONArray creditors = (JSONArray) simpleCreditorsObject;
This exception shows:
class java.util.ArrayList cannot be cast to class org.json.simple.JSONArray (java.util.ArrayList is in module java.base of loader 'bootstrap'; org.json.simple.JSONArray is in unnamed module of loader 'app')
It seems like the Object isn't instanceOf JSONArray but i can't get why.
Is it a totally wrong attempt or am I missing a part?
Well, you can easily diagnose the problem by replacing
if(simpleCreditorsObject instanceof JSONArray) {
System.out.println("worked");
}
with:
if(simpleCreditorsObject instanceof JSONArray) {
System.out.println("worked");
} else {
System.out.println("class: " + simpleCreditorsObject.getClass().getName());
}
But I suggest to switch from json.simple library to Jackson JSON library. See those links: Jackson JSON Tutorial, Jackson on github and Maven repositories. Also, just to simplify your task you can use Another open source library that provides a simple wrapper over Jackson JSON library. in this case your code may look like this (assuming that you your input String param contains your JSON String:
{ "paymentId" : 123, "creditors" : [ { "id" : 1, "name" : "name1" }, { "id" : 2, "name" : "name2" } ] }
the method may look as folows:
public void parseJson(String input) {
try {
Map<String, Object> myMap = JsonUtils.readObjectFromJsonString(input, Map<String, Object>.class);
List<Map<String, Object>> creditors = (List<>)myMap.get("creditors");
System.out.println("Number of creditors: " + creditors.size());
System.out.println("Creditor names:");
for(Map<String, Object>> map : creditors) {
System.out.println(map.get("name"));
}
} catch(Exception e) {
e.printStacktrace();
}
}
Here is the JavaDoc for the JsonUtils class. The library could be found as Maven artifact and on Github (including source code and Javadoc).

How to create a json file using existing json file as template?

I have a json file which is mostly standard for all my work, the only difference is few parameters.
Now I want to know how can I using java use this json file as a template and provide the parameters as input and save the new json file on local directory?
{
"key" : "HWM_NAME",
"value" : "PINE_SLS_SVC_CUST_CNTCT"
}, {
"key" : "TOPIC",
"value" : "SLS_SVC_CUST_CNTCT2"
}, {
"key" : "SRC_SCHEMA",
"value" : "party_pkg"
}, {
"key" : "SRC_TABLE",
"value" : "SLS_SVC_CUST_CNTCT"
}, {
"key" : "TGT_SCHEMA",
"value" : "mstrdata_hub"
}, {
"key" : "TGT_TABLE",
"value" : "SLS_SVC_CUST_CNTCT"
} ]
},
So here I wish to just change the Value: "PINE_SLS_SVC_CUST_CNTCT" to some other value that I would take as input from user and give me a new json file with those values.
PS: I am working on Java Swing to create a GUI to get the parameters from the user and provide the json file as output.enter image description here
this is how GUI looks
Consider using some JSON Library, for example GSon
Read the values from json
List<LinkedTreeMap> values = gson.fromJson(json, ArrayList.class);
...
update the values, here you can write values from UI components!!!!
for (LinkedTreeMap pair : values) {
//Update values
System.out.println(pair.toString());
}
And generate JSON from java objects
import com.google.gson.Gson;
import com.google.gson.internal.LinkedTreeMap;
...
Gson gson = new Gson();
String json = gson.toJson(values);

Cloudera Navigator API fail to fetch nested data

I am working in Cloudera Manager Navigator REST API where extracting result is working fine, but unable to get any nested value.
The type of data is extracting as below.
{
"parentPath": "String",
"customProperties": "Map[string,string]",
"sourceType": "String",
"entityType": "String"
}
And data should be like
{
"parentPath": "abcd",
"customProperties": {
"nameservice" : "xyz"
},
"sourceType": "rcs",
"entityType": "ufo"
}
But I am getting key-value result as follows.
parentPath :abcd
customProperties : null
sourceType : rcs
entityType : ufo
In above response data, "customProperties" is coming with a null value where it should return a map object contains ["nameservice" : "xyz"]. This is the problem with following code snippet.
MetadataResultSet metadataResultSet = extractor.extractMetadata(null, null,"sourceType:HDFS", "identity:*");
Iterator<Map<String, Object>> entitiesIt = metadataResultSet.getEntities().iterator();
while(entitiesIt.hasNext()){
Map<String, Object> result = entitiesIt.next();
for(String data : result.keySet()){
System.out.println(" key:"+data+" value:"+result.get(data));
}
}
Can you suggest me how to get the nested value where datatype is complex.
have u checked how the data looks on navigator ui? You can first verify that once, and also try cloudera /entities/entity-id rest API in browser to check how json response is coming

Jackson Json accesing JsonNode property name

I have a schema like this:
{
"type" : "object",
"$schema" : "http://json-schema.org/draft-03/schema#",
"id" : "urn:jsonschema:com:vlashel:dto:UserDto",
"description" : "this is the top description",
"title" : "this is the top title",
"properties" : {
"number" : {
"type" : "integer"
"required" : true
},
"password" : {
"type" : "string"
"required" : true
}
}
I have the following code that converts this shcema draft 3 to draft 4 by removing "required", I want to collect nodes property names that have 'requred' in them. How do I do that? I don't see methods for this..
JsonNode jsonNode = jsonNodeIterator.next();
ObjectNode element;
if (jsonNode instanceof ObjectNode) {
element = (ObjectNode) jsonNode;
element.remove("required");
String propertyName = element.getPropertyName(); //I'm looking for this kind of method.
Thanks!
You can get all of the nodes that have that property by using the List<JsonNode> findParents(String fieldName), which does that this for you. From the docs:
Method for finding a JSON Object that contains specified field, within
this node or its descendants. If no matching field is found in this
node or its descendants, returns null.
I made a quick example but had to add a few characters to the JSON blob you posted as it is missing some commas and a bracket and can't be read by the ObjectMapper. It is as simple as this:
JsonNode root = mapper.readTree(SCHEMA);
List<JsonNode> required = root.findParents("required");
for (JsonNode node: required) {
Object prettyOutput = mapper.readValue(node, Object.class);
System.out.println(mapper.writerWithDefaultPrettyPrinter().writeValueAsString(prettyOutput));
}
Output:
{
"type" : "integer",
"required" : true
}
{
"type" : "string",
"required" : true
}

How to create JSON Schema for Name/Value structure?

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)

Categories