How to get the set inside nested JsonNode using Jackson - java

I have a below JSON structure. which I need to parse using the Jackson library. I am building a web-service, which accept below JSON in a POST method's BODY.
{
"organization": {
"products": [
"foo",
"bar",
"baz"
]
},
"mission" : "to be the best in domain"
}
Till, now I was having simple JSON body, which wasn't having nested and JSON element, like in this case organization is another JSON node which contains a Set of products.
This JSON keys are not mandatory, And I am accepting/storing organization JSON in JsonNode. And doing below checks.
If organization is null.
If organization is not null and it has products key.
But after that I don't know how to fetch the set of boards from this JsonNode and store it in Java's HashSet.
My expected O/P should be to have a set of boards extracted from my organization JsonNode.
P.S. :- I think I have to use the ObjectMapper but couldn't find a direct way of getting the Set. Looks like I need to use some JsonParser with which I am not very familier.

You can create DTOs(Data Transfer Objects) for your purpose. The nested objects could have the structure as below:
class Organization {
List<String> Products;
.....
}
class WebOrganizationRequest {
Organization organization;
String mission;
}
By creating objects in this way you are mapping your JSON objects to classes and Jackson will typecast the JSON as an instance of WebOrganizationRequest when you pass it in the controller with WebOrganizationRequest as the request body type.

Related

Remove Elements from JSON String

I have a JSON string as follows:
{
"account": "1234",
"type": "ar-type",
"eventTypes": "Update",
"objectClassName": "com.triype",
"objectJson": "{\"Name\":\"pdpot\",\"traptype\":\"adpot",\"displayName\":\"pdpot",\"experimentName\":\"pdpotpie\",\"creationTime\":\"Mar 18, 2020 5:58:58 PM\",\"createdBy\":{\"userProfileOne\":\"s:pdx\",\"userProfileTwo\":\"sid\",\"domainId\":\"did:pdx-tod-64003\"},\"lastModifiedBy\":{\"userProfileArn\":\"s:pdx-tod-64003\"},\"createdBy\":{\"userProfileOne\":\"s:p\",\"userProfileTwo\":\"si\",\"domainId\":\"did:ppot\"}}}
}
I get this input as a string and before passing it as a string to a parser I need to perform some string filtering and remove all "userProfileOne", "userProfileTwo","domainId" and their keys, without compromising the JSON structure. I am currently writing this code in Java using gson and json.
Note: There are multiple occurences of UserProfileOne, UserProfileTwo and DomainID.
The required Output is as follows:
{
"account": "1234",
"type": "ar-type",
"eventTypes": "Update",
"objectClassName": "com.triype",
"objectJson": "{\"Name\":\"pdpot\",\"traptype\":\"adpot",\"displayName\":\"pdpot",\"experimentName\":\"pdpotpie\",\"creationTime\":\"Mar 18, 2020 5:58:58 PM\"}}
}
Currently I am using substringBetween. But the operation does not work as intended.
A potential approach is to deserialize the json into a java structure then filter this structure by set to null fields you don't want to be serialize.
By using framework like Jackson you can set this before serialization on the ObjectMapper
mapper.setSerializationInclusion(Include.NON_NULL). So all null values won't be serialized in the final json/result.
I think the best maintainable way would be to create a class structure corresponding to that json and map it to the class.
Use #JsonIgnore on the fields to be ignored and then map it back to JSON from the class structure.
Another approach, a bit complex to implement, is to go through each node in the json and remove that node if it's not required
You can also do it by string matching but I don't think that is a good approach.

Spring Boot and RethinkDB save JSON of unknown structure

I develop Spring REST API. One of its endpoints must receive JSONs of unknown structure. To be exact, all JSONs has common header, but the inner document differs:
{
"receiveData": {
"iBusData": {
"requestUID": "11111111-2222-3333-4444-555555555555",
"messageKind": "PublishedData",
"sender": "ST-DELLIN-307",
"senderDateTime": "2018-10-15T09:09:09",
"typeName": "typeContractor",
"currentSenderApplication": "GP",
"objectUID": "09876543-rrrr-aaaa-nnnn-ddddddddddddd",
"data": {
"contractor": {
"uid": "09876543-rrrr-aaaa-nnnn-ddddddddddddd",
"name": "Test_Contractor",
"marked": false,
"code": "763764568763",
"isGroup": false,
"fullName": "Test_Contractor",
"INN": "Test_Contractor",
"personalIDKindName ": "Test_Contractor",
"personalIDSeries": "7634",
"personalIDNumber": "18-111111111",
"contractorCategory": "Test_Contractor",
"contractorOPF": "Test_Contractor",
"federalCategory": "Test_Contractor",
"regionalCategory": "Test_Contractor"
}
}
}
}
}
Payload of data field may be different. All this nested documents (contractor in the example above) need to be stored in JSON-oriented database RethinkDB.
How to implement endpoint that cat receive JSONs with different structured in the data field?
Now I thought up to parse all JSONs as HashMap:
public ResponseEntity<?> all(#RequestBody HashMap json)
split HashMap to header and document and to store in database. But there are some difficulties:
I need to select stored documents in the same format that they comes to endpoint
I need to compare nested documents using SHA256 and update them in the database
I need to add three custom fields to the document before storing in the database
How to do all this?
You can create a classes for the body that has the common fields [you call a header].
Request body class
class MyRequest {
BusData iBusData;
}
Class to hold the dynamic data
class BusData {
String requestUID;
String messageKind;
// other fields
// unknown json structure
HashMap<String, Object> data;
}
When you receive this type of request body, to insert in reThinkDB - I think you could iterate the keys/values in the hashmap, and determine if the value is another object, then recursively iterate, building a query.
You'll probably need to pass the querybuilder parts by reference to methods during the recursion.
I don't have experience with rethinkdb, so I can't provide an implementation here.

Deserialize only some fields of JSON objects array (Java)

Given this JSON response I get from an website :
{
"Items":
[
{ "Name":"Apple", "Price":12.3, "Quantity":30 },
{ "Name":"Grape", "Price":3.21, "Quantity":60 }
],
"Date":"21/11/2010"
}
How could i deserialize this JSON, splitting it in an array called Fruits, containing only name and quantity ? I don't care about date field or other fields like price.
My class should look like:
class Fruit{
String name;
String quantity;
}
And this is the array:
Fruit myfruits[] = new Fruit [this number depends on JSON response I get]
How could I achive this ?
I've tried to give my best explanation, if it is still not clear, feel free to ask.
P.S: btw, the real JSON response has many more fields
You need to ignore the fields you don't wont.
Each serialization frameworks does it in different ways.
In some you can add annotations to you POJO, or set it with the serializer instance
Using Gson:
Gson ignore json field and deserialize
Using Jackson:
Ignoring new fields on JSON objects using Jackson

Incongruity between Cloudify documentation for a REST response and the one I get

I have a Cloudify 2.7.0 instance running.
I need to access Cloudify's API from a Java application and I found an incongruity between the returned JSON and the one which is documented in the Cloudify documentation.
The API is
/service/applications
In the documentation I can read that it should return the following JSON string
{
"status" : "success",
"response" : [ "petclinic", "travel" ]
}
But if I do the same request to my Cloudify instance I get the following JSON string
{
"status" : "success",
"response" : {
"petclinic": "",
"travel":""
}
}
In the java application the JSON information is stored in the following POJO (generated with JSONSchema2POJO)
// CloudifyResponse.java
public class CloudifyResponse {
#JsonProperty("response")
private Response response;
#JsonProperty("status")
private String status;
// getters and setters
}
// Response.java
public class Response {
#JsonProperty("helloworld")
private String helloworld;
#JsonProperty("petclinic")
private String petclinic;
// getters and setters
}
I use the Jackson library to deserialize JSON into POJO. As you can see the JSON string is deserialized into a POJO in which every istantiated application is a POJO's field.
This might be a big problem for the development of the application. In fact, as the instances of the application change, the returned JSON changes and we need to update the POJO structure, something I can't do at runtime.
Do you know whether the Cloudify API has changed the response JSON structure? Is there any way to get the documented JSON output instead of the one I get.
Thank you in advance
Giulio
As of 2.7 The service controller (which you are referring to here) is deprecated, and actually remains available for backward compatibility. The documentation is indeed wrong regarding the returned json structure.
My advice is to use the updated API
/{version}/deployments/applications/description
As documented here, this API actually returns a json holding a list of ApplicationDescription objects, so as application are deployed the response structure remains essentially the same, but the contained list grows.

How do I do polymorphic JSON deserialisation with Jackson based on attribute in parent class?

We have the following Json:
{
"type" : "1",
"otherStuff" : "2",
...
"items" : [
{
"commonItemAttribute" : "value",
"specificToType1" : "whatever"
...
}
]
}
We need to polymorphically deserialise the items into different sub classes based on the type attribute.
Is it possible in a custom Jackson deserialiser to get the type value?
Can we safely look back up the Json tree using the JsonParser given to the deserialize method?
I found this blog about polymorphic deserialisation but it seems to require a type attribute on the items themselves.
Thanks
This kind of JSON is not supported, since while "External" type ids of form:
{ "childType" : "SomeTypeId",
"child" : { .... }
}
are supported (with #JsonTypeInfo.As.EXTERNAL_PROPERTY), they only work for simple types, not for Collections or Maps.
So if you can't change JSON to be bit more standard (including type id for elements is the standard way), you will need to use custom serializers, deserializers.

Categories

Resources