I try to map dynamic fields of a document in mongodb collection to a model in spring boot project,
well this is the document from mongodb
Example of MongoDB Document
{
"_id":"5f78e5599fe104f27eb61333",
"conducteur":{
"cin":"F21458",
"nomComplet":"Ahmed Ayoub",
"idConducteur":"4"
},
"vehicule":{
"matricule":"4585|45| a",
"engin":"Benne",
"idVehicule":"1"
},
"date":"21-11-2019 22:07:44",
"site":"Paris",
"rating":37.04,
"etat":true,
"imageUrl":null,
"motif":"nothing",
"controlleur":{"cin":"F44585","nomComplet":"Test","idController":"2"},
"checklistConducteur":[false,true,false,true,true],
"checklistEquipement":[false,false,false,true,true],
"checklistEngin":[false,true,true,false,true,false,true],
"checklistAttelage":[true,true,true,false,true]
}
Then I create the model with the standards or fixed fields and one field to handle dynamic properties, the model seems like
#Document(collection = "checkList")
public class CheckList {
private String id;
private Map<String, String> conducteur;
private Map<String, String> vehicule;
private Date date;
private String site;
private double rating;
private boolean etat;
private String imageUrl;
private String motif;
private Map<String, String> controlleur;
private Map<String, Boolean[]> catchAll = new HashMap<>();
public Map<String, Boolean[]> getCatchAll() {
return catchAll;
}
#JsonAnySetter
public void setCatchAll(Map<String, Boolean[]> catchAll) {
this.catchAll = catchAll;
}
}
So what i want is to combine or map checklistConducteur, checklistEquipement, checklistEngin and checklistAttelage from mongodb document to the field catchAll, or to get nested inside it.
I tried to use the annotations like #JsonAnyGetter, #JsonAnySetter, or to create a class CatchAll have these properties, but give me the same result:
API Response:
{
"id": "5f78e5599fe104f27eb61333",
"conducteur": {
"cin": "F21458",
"nomComplet": "Ahmed Ayoub",
"idConducteur": "4"
},
"vehicule": {
"matricule": "4585|45| a",
"engin": "Benne",
"idVehicule": "1"
},
"date": "21-11-2019 22:07:44",
"site": "Paris",
"rating": 37.04,
"etat": true,
"imageUrl": null,
"motif": "nothing",
"controlleur": {
"cin": "F44585",
"nomComplet": "Test",
"idController": "2"
},
"catchAll": {}
}
what i want as result from API:
"catchAll": {
"checklistConducteur":[false,true,false,true,true],
"checklistEquipement":[false,false,false,true,true],
"checklistEngin":[false,true,true,false,true,false,true],
"checklistAttelage":[true,true,true,false,true]
}
If anyone has a solution or suggestion please help me, I will be thankful.
Related
I have a Cosmos DB and want to write different kind of documents to it. The structure of the documents is dynamic and can change.
I tried the following. Let's say I have the following class:
class CosmosDbItem implements Serializable {
private final String _id;
private final String _payload;
public CosmosDbItem(String id, String payload) {
_id = id;
_payload = payload;
}
public String getId() {
return _id;
}
public String getPayload() {
return _payload;
}
}
I can create then the document with some JSON as follows:
CosmosContainer _container = ...
CosmosDbItem dataToWrite = new CosmosDbItem("what-ever-id-18357", "{\"name\":\"Jane Doe\", \"age\":42}")
item = _cosmosContainer.createItem(dataToWrite, partitionKey, cosmosItemRequestOptions);
This results in a document like that:
{
"id": "what-ever-id-18357",
"payload": "{\"name\":\"Jane Doe\", \"age\":42}",
"_rid": "aaaaaaDaaAAAAAAAAAA==",
"_self": "dbs/aaaaAA==/colls/aaaaAaaaDI=/docs/aaaaapaaaaaAAAAAAAAAA==/",
"_etag": "\"6e00c443-0000-0700-0000-5f8499a70000\"",
"_attachments": "attachments/",
"_ts": 1602525607
}
Is there a way in generating the payload as real JSON object in that document? What do I need to change in my CosmosDbItem class? Like this:
{
"id": "what-ever-id-18357",
"payload": {
"name":"Jane Doe",
"age":42
},
"_rid": "aaaaaaDaaAAAAAAAAAA==",
"_self": "dbs/aaaaAA==/colls/aaaaAaaaDI=/docs/aaaaapaaaaaAAAAAAAAAA==/",
"_etag": "\"6e00c443-0000-0700-0000-5f8499a70000\"",
"_attachments": "attachments/",
"_ts": 1602525607
}
Here is my solution that I ended up. Actually it is pretty simple once I got behind it. Instead of using CosmosDbItem I use a simple HashMap<String, Object>.
public void writeData() {
...
Map<String, Object> stringObjectMap = buildDocumentMap("the-id-", "{\"key\":\"vale\"}");
_cosmosContainer.createItem(stringObjectMap, partitionKey, cosmosItemRequestOptions);
...
}
public Map<String, Object> buildDocumentMap(String id, String jsonToUse) {
JSONObject jsonObject = new JSONObject(jsonToUse);
jsonObject.put("id", id);
return jsonObject.toMap();
}
This can produce the following document:
{
"key": "value",
"id": "the-id-",
"_rid": "eaaaaaaaaaaaAAAAAAAAAA==",
"_self": "dbs/eaaaAA==/colls/eaaaaaaaaaM=/docs/eaaaaaaaaaaaaaAAAAAAAA==/",
"_etag": "\"3b0063ea-0000-0700-0000-5f804b3d0000\"",
"_attachments": "attachments/",
"_ts": 1602243389
}
One remark: it is important to set the id key in the HashMap. Otherwise one will get the error
"The input content is invalid because the required properties - 'id; ' - are missing"
I am not able to map a consumed json to another json to each element by using REST template in Spring Boot
Controller code:
public List<Getrequests> getallrequests() {
List<Getrequests> list=Serviceobj.allrequestdata();
return list;
}
Service code:
public List<Getrequests> allrequestdata() {
String urlGETList = "http://localhost:8082/myapp/userinfo/getusertype/asd454";//get by id call
ResponseEntity<Usertype[]> responseEntity =resttemplateobj.getForEntity(urlGETList, Usertype[].class);
Usertype[]objects = responseEntity.getBody();
List results = admininfoDaoobj.getallrequestsdata();
//results.add(objects);if i un comment this line of code i am getting 1 output means it just add to the list only
return results;
}
Dao code:
public List<Getrequests> getallrequestsdata(){
String hql = "FROM Createrequest";
HttpHeaders headers = new HttpHeaders();
headers.setAccept(Arrays.asList(MediaType.APPLICATION_JSON));
Query<Createrequest> query = getSession().createQuery(hql,Createrequest.class);
List resultlist= query.getResultList();
return resultlist;
}
Getrequests pojo class:
public class Getrequests{
private String userid;
private String username;
private String userphoneno;
.......getters and setters.....
}
User type pojo class:
public class Usertype{
private String usertype;
private String useraddress;
.......getters and setters.....
}
1 output:
[
{
"userid":"asd454",
"username":"satya",
"userphoneno":"1234567890"
},
{
"userid":"asd455",
"username":"satya",
"userphoneno":"1234567890"
}
[
{
"usertype":"admin,agent",
"useraddress:"dsadasd,asdasdsa"
},
{
"usertype":"agent",
"useraddress:"asdasdsa"
},
]
]
2 output
If I comment resultlist.add(objects) in Service code means it's not added to the getrequest list then I am getting below output:
[
{
"userid":"asd454",
"username":"satya",
"userphoneno":"1234567890"
},
{
"userid":"asd455",
"username":"satya",
"userphoneno":"1234567890"
}
]
But I need to map for each userid, I need to display the usertype and user address like below output.
3 Output
[
{
"userid":"asd454",
[
{
"usertype":"admin,agent",
"useraddress:"dsadasd,asdasdsa"
} ]
"username":"satya",
"userphoneno":"1234567890"
},
{
"userid":"asd455",
[
{
"usertype":"agent",
"useraddress:"asdasdsa"
}
]
"username":"satya",
"userphoneno":"1234567890"
}
]
I also tried the rest template call in Dao then also not getting.
How can I map for each userid to display the usertype and user address like as above shown 3 output.
From your snippets, it looks like you want to generate a specific POJO signature.
There are plenty of tools which can give you a stub out of a sample json request.
From your example, i would guess that changing the Getrequests would do the trick,
like :
public class Getrequests{
private String userid;
private String username;
private String userphoneno;
private Usertype userType;
.......getters and setters.....
}
You might need to change it to a list reference as well, depending on your schema and your overall requirement.
EDIT
public class Getrequests{
private String userid;
private String username;
private String userphoneno;
private List<Usertype> userType;
}
If i make the reference a list, then the below samples are the output :
Single object:
{
"userid":"69",
"username":"asd",
"userphoneno":"09876",
"userType":[
{
"usertype":"01",
"useraddress":"1234"
}
]
}
As An array :
[
{
"userid":"94",
"username":"asd",
"userphoneno":"09876",
"userType":[
{
"usertype":"01",
"useraddress":"1234"
}
]
},
{
"userid":"53",
"username":"asd",
"userphoneno":"09876",
"userType":[
{
"usertype":"01",
"useraddress":"1234"
}
]
}
]
Is there any way to write Json array list in application.properties file (spring-boot), so that I can read whole Json with minimum code?
Below is my json object.
{ "userdetail": [
{
"user": "user1",
"password": "password2",
"email": "email1"
},
{
"user": "user2",
"password": "password2",
"email": "email2"
}]}
And also if I use jasypt to encode password, then what the code will be?
Refer to Spring Boot Docs here
You can use YAML
my:
servers:
- dev.example.com
- another.example.com
or normal configuration property arrays:
my.servers[0]=dev.example.com
my.servers[1]=another.example.com
Than you can load these properties into application this way:
#ConfigurationProperties(prefix="my")
public class Config {
private List<String> servers = new ArrayList<String>();
public List<String> getServers() {
return this.servers;
}
}
For your case I would try something like:
users.userdetail[0].user=..
users.userdetail[0].password=..
...
And read it via
#ConfigurationProperties(prefix="users")
public class Userdetail {
private class User {
public String user;
public String password;
public String email;
}
private List<User> userdetails = new ArrayList<User>();
public List<User> getUserdetails() {
return this.userdetails;
}
}
My current project employs GraphQL.
I wish to investigate Moshi as my Json parser however I am experiencing difficulties in generating my GraphQL response json
This is the Json Request message format I require:
{
"operationName": "androidMyQuery",
"query": "query androidMyQuery .......",
"variables": {
"foo": 400,
"bar": 200,
"baz": "1970-01-01T00:00:00.000Z"
}
}
This is what Moshi generates:-
{
"operationName": "androidMyQuery",
"query": "query androidMyQuery .......",
"variables": {
"variables": {
"foo": 400,
"bar": 200,
"baz": "1970-01-01T00:00:00.000Z"
}
}
}
My Java model classes resemble this:-
public class GraphqlRequest {
#Json(name = "operationName")
private String operationName;
#Json(name = "variables")
private Variables variables;
#Json(name = "query")
private String query;
}
And
public class Variables {
private Map<String, Object> variables = new HashMap<>();
public Map<String, Object> getVariables() {
return this.variables;
}
public void setVariable(final String name, final Object value) {
this.variables.put(name, value);
}
}
How do I achieve my desired result and keep the model classes above?
My API needs to return a list of entry objects from the JSON below. I am using jersey and jackson. I would ideally like to only create a java class PermissionEnty , and my API to return a list of PermissionEntry objects from the JSON. I am not able to deserialize using the below approach? Can someone advise what could be the issue? I have added UNWRAP_ROOT_VALUE so I presume the 'list' node it ignored, and I would get items below 'list' node.
public class PermissionEntry {
private String id;
private String displayName;
private String memberType;
}
and the json;
{
"list": {
"pagination": {
"count": 5,
"hasMoreItems": false,
},
"entries": [
{
"entry": {
"displayName": "norma",
"id": "norma",
"memberType": "PERSON"
}
},
{
"entry": {
"displayName": "clara",
"id": "clara",
"memberType": "PERSON"
}
},
{
"entry": {
"displayName": "michael",
"id": "mich",
"memberType": "PERSON"
}
}
]
}
}
PermissionEntries
public class PermissionEntries {
#JsonProperty(value = "entries")
#JsonDeserialize(using = PermissionEntryDeserializer.class)
private List<PermissionEntry> entries;
public List<PermissionEntry> getEntries() {
return entries;
}
public void setEntries(List<PermissionEntry> entries) {
this.entries = entries;
}
}
Below is the deserializer that I am using
public class PermissionEntryDeserializer extends JsonDeserializer<List<PermissionEntry>> {
private static final String ENTRY = "entries";
private static final ObjectMapper mapper = new ObjectMapper()
.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
private static final CollectionType collectionType =
TypeFactory
.defaultInstance()
.constructCollectionType(List.class, PermissionEntry.class);
#Override
public List<PermissionEntry> deserialize(JsonParser jsonParser, DeserializationContext deserializationContext)
throws IOException {
ObjectNode objectNode = mapper.readTree(jsonParser);
JsonNode nodeEntries = objectNode.get(ENTRY);
if (null == nodeEntries // if no ENTRY node could be found
|| !nodeEntries.isArray() // or ENTRY node is not an array
|| !nodeEntries.elements().hasNext()) // or ENTRY node doesn't contain any entry
return null;
return mapper.readerFor(collectionType).readValue(nodeEntries);
}
}
Service API
public Optional<List<PermissionEntry>> getPermissionsForGroup(String groupName) {
Response response = getTarget()
.path("/api/group/" + groupName + "/members")
.request()
.get();
PermissionEntries list = response.readEntity(PermissionEntries.class);
}
I don't understand what you mean in this question 'Can someone please tell me how many java classes do I need to create to get a list of entries.' but you had already an entry object called PermissionEntry. You will have the list of this object.
This is the jersey client of your data with jakcson .
ClientConfig clientConfig = new DefaultClientConfig();
clientConfig.getFeatures().put(JSONConfiguration.FEATURE_POJO_MAPPING, Boolean.TRUE);
Client client = Client.create(clientConfig);
String URL = "http://{{host}}:{{port}}/entry";
WebResource webResourceGet = client.resource(URL);
ClientResponse response = webResourceGet.accept("application/json").get(ClientResponse.class);
String output = response.getEntity(String.class);
ResponseList responseList= mapper.readValue(output , ResponseList .class);//here is the permissionEntry list that you wil have
Also, you should create an object given name as Pagination for pagination that is in the json data. You can make an another object that includes List<PermissionEntry> and Pagination called ResponseList.