How to create a nested json using collections in java - java

I am creating a Json format for my nav bar menu and menu items.. i have put some effort and have done some work for one loop but what i want is to be nested json
My database has Data like This
What i want is to create a Json format from this table like this
var data = {
"India":
[
{ "Submenu": "delhi", "link" : "https://www.google.com" },
{ "Submenu": "mumbai", "link" : "https://www.google.com" }
],
"USA":
[
{ "Submenu": "NY", "link" : "https://www.google.com" },
{ "Submenu": "california", "link" : "https://www.google.com" }
],
"England":
[
{ "Submenu": "London", "link" : "https://www.google.com" },
{ "Submenu": "Menchester", "link" : "https://www.google.com" }
],
"logout":
[]
};
Till now i have tried this
LinkedHashMap<Object, Object> lhm = null;
List<Map<Object, Object>> list = new ArrayList<Map<Object, Object>>();
String sql="select menu,submenu and link from table_name";
String name,link;
String str = null;
Gson gson = new Gson();
try {
resultSet = statement.executeQuery(sql);
while(resultSet.next()){
lhm= new LinkedHashMap<Object, Object>();
name= resultSet.getString("submenu");
link= resultSet.getString("link");
lhm.put("submenu", name);
lhm.put("link", link);
list.add(lhm);
str = gson.toJson(list);
}
System.out.println(str);
from this i am getting result like this
[{"submenu":"Delhi","link":"https://www.google.com"},{"submenu":"mumbai","link":"https://www.google.com"},{"submenu":"NY","link":"https://www.google.com"},{"submenu":"California","link":"https://www.google.com"},{"submenu":"London","link":"https://www.google.com"},{"submenu":"Mencherter","link":"https://www.google.com"}]
now i have got the sub menus and there link .. i am facing trouble on linking the submenus to there respective menus .. i am facing issue in looping the data acc to my requirement if anyone of you have any suggestion and idea please help me out

First retrieve required dat from DB:
select menu, sub-menu, link from table_name;
Then create a Map to hold a menu content:
Map<String, List<Map<String, String>> map = new LinkedHashMap<>();
Then read result sets and fill a map, using menu name as a key:
while(rs.next()) {
map.compute(rs.getString("menu"), (menu, subMenus) -> {
Map<String, String> mapSubMenu = new LinkedHashMap<>();
mapSubMenu.put("Submenu", rs.getString("sub-menu"));
mapSubMenu.put("link", rs.getString("link"));
subMenus = subMenus != null ? subMenus : new ArrayList<>();
subMenus.add(mapSubMenu);
return subMenus;
});
}

Try Using Map<String,List<Map<Object, Object>>> instead of List<Map<Object, Object>> so that you can give menu name to your main menu.
LinkedHashMap<Object, Object> lhm; //initiaze
Map<String,List<Map<Object, Object>>> map;
List<Map<Object, Object>> list;
while(rs.next())
{
String menu = rs.getString("menu");
String subMenu = rs.getString("sub-menu");
String link = rs.getString("link");
lhm.put("submenu", name);
lhm.put("link", link);
if (map.containsKey(menu)) //check if mainmenu already present
{
map.get(menu).add(lhm);
}
else
{
//initialize list here
list.add(lhm);
map.put(menu,list);
}
}
str = gson.toJson(list);
Follow idea only and customize code as your need

Related

Remove duplicate from object and merge in array

Code sample:-
public List<UserDto> getUserCandidates(String taskId) {
List<UserCandidates> listResponse;
ResponseEntity<String> response=restTemplate.getForEntity(configProperties.getUrl()+"/task/"+taskId+"/identity-links",
String.class);
listResponse =new Gson().fromJson(response.getBody(), new TypeToken<ArrayList<UserCandidates>>(){}.getType());
listResponse.forEach(result->{
if(!StringUtils.isEmpty(result.getUserId())){
ResponseEntity<UserRefer> userResponse=restTemplate.getForEntity(configProperties.getUrl()+"/user/"+result.getUserId()+"/profile", UserRefer.class);
userDtoList.add(new UserDto(result.getUserId(), Arrays.asList(result.getGroupId()), Arrays.asList(result.getType()), userResponse.getBody().getFirstName(),
userResponse.getBody().getLastName(), userResponse.getBody().getEmail()));
}
else if(!StringUtils.isEmpty(result.getGroupId())) {
ResponseEntity<String> responseGroup=restTemplate.getForEntity(configProperties.getUrl()+"/user"+"?memberOfGroup="+result.getGroupId(), String.class);
List<UserResponse> listGroup=new Gson().fromJson(responseGroup.getBody(), new TypeToken<ArrayList<UserResponse>>(){}.getType());
listGroup.forEach(resultGroup->{
userDtoList.add(new UserDto(resultGroup.getId(),Arrays.asList(result.getGroupId()),
Arrays.asList(result.getType()),resultGroup.getFirstName(),resultGroup.getLastName(),resultGroup.getEmail()));
});
}
});
return userDtoList;
}
So in if condition the response from API I'm getting is
UserRefer(id=demo, firstName=Demo, lastName=Demo, email=demo#camunda.org) - userResponse object
And from listResponse object data is [UserCandidates(userId=null, groupId=accounting, type=candidate), UserCandidates(userId=null, groupId=sales, type=candidate), UserCandidates(userId=demo, groupId=null, type=assignee)]
next in else if condition the response for listGroup is [UserResponse(status=null, id=demo, firstName=Demo, lastName=Demo, email=demo#camunda.org), UserResponse(status=null, id=mary, firstName=Mary, lastName=Anne, email=mary#camunda.org)]
So now you can see the data is duplicate. The output i want is for when userId is not empty from the data it should take type and merge the array
else if grouped not empty the data it should take for groupType and merge in the array removing duplicte and merging in same object
Output :-
[
{
"userId": "demo",
"name": "Demo Demo",
"type": [
"candidate",
"assignee"
],
"email": "demo#camunda.org",
"groupId": [
"accounting",
"sales"
]
},
{
"userId": "mary",
"name": "Mary Anne",
"type": [
"candidate"
],
"email": "mary#camunda.org",
"groupId": [
"accounting",
"sales"
]
}
]
You need some fundamental changes in your code.
1- instead of using ResponseEntity<String> use ResponseEntity<UserCandidates[]> response by this changing you don't need use Gson() dependency.
2- You don't need to use StringUtils to check to be empty. there is same method for both string and list objects.
3- For the duplicate date I define a Map<String,UserDto> with id as key and userDto object as a value. and where the userDto data is created I store it in the map with the id. as you see for storing userDto object in the map I used merge method that for the duplicate key(id) it has a merge function.
Tip: for readability would be nice to separate the restTemplate call in other class may you reuse it too.
mergeFunction is somthing like this:
private UserDto mergeFunction(UserDto u1,UserDto u2){
u1.getType().addAll(u2.getType());
u1.getGroupId().addAll(u2.getGroupId());
return u1;
}
and complete code is:
public List<UserDto> getUserCandidates(String taskId) {
Map<String, UserDto> userDtoMap = new HashMap<>();
Map<String, String> params = new HashMap<>();
ResponseEntity<UserCandidates[]> response = restTemplate
.getForEntity(configProperties.getUrl() + "/task/" + taskId + "/identity-links",
UserCandidates[].class, params);
Arrays.asList(response.getBody()).forEach(result -> {
if (!result.getUserId().isEmpty()) {
ResponseEntity<UserRefer> userResponse = restTemplate
.getForEntity(configProperties.getUrl() + "/**", UserRefer.class);
userDtoMap.merge(result.getUserId(), new UserDto(result.getUserId(),
new ArrayList<>(Arrays.asList(result.getGroupId())), Arrays.asList(result.getType()),
userResponse.getBody().getFirstName(),
userResponse.getBody().getLastName(),
userResponse.getBody().getEmail()), (u1, u2) -> mergeFunction(u1,u2));
} else if (!result.getGroupId().isEmpty()) {
String requestUri = configProperties.getUrl() + "/user" +
"?memberOfGroup={memberOfGroup}";
Map<String, String> userResParam = new HashMap<>();
userResParam.put("memberOfGroup", result.getGroupId());
ResponseEntity<UserResponse[]> responseGroup = restTemplate
.getForEntity(requestUri, UserResponse[].class, userResParam);
Arrays.asList(responseGroup.getBody()).forEach(resultGroup -> {
userDtoMap.merge(resultGroup.getId(), new UserDto(resultGroup.getId(),
Arrays.asList(result.getGroupId()),
Arrays.asList(result.getType()), resultGroup.getFirstName(),
resultGroup.getLastName(),
resultGroup.getEmail()), (u1, u2) -> mergeFunction(u1,u2));
});
}
});
return new ArrayList<>(userDtoMap.values());
}

how to declare a java bean for the below json structire

I have below json response as part of a webservice response ,where inner object name is value which is dynamic.Not able to understand how to declare a equivalent java bean...
{
"error": [
{
"fea09b93175b626e4bb3d248ccb890bc": {
"name": "80_5595_10.zip (5.0)",
"error": [
"Location path does not exist"
]
}
},
{
"5a8745c1967adabe9d492d3595f37ce1": {
"name": "80_7208_01.zip (5.0)",
"error": [
"Location path does not exist"
]
}
}
]
You could do it that way (example using Jackson).
I declared a bean as follow:
class Error {
String id;
String name;
List<String> error;
// Getters / Setters
#Override
public String toString() {
return "id="+id+", name="+name+", error="+error;
}
}
Your JSON structure is Map<String, List<Map<String, Error>>>
// Parse your JSON into a Map<String, List<Map<String, Error>>>
ObjectMapper mapper = new ObjectMapper();
Map<String, List<Map<String, Error>>> map =
mapper.readValue(json, new TypeReference<Map<String, List<Map<String, Error>>>>() {});
You now have this Map structure
{ error = [
{ fea09b93175b626e4bb3d248ccb890bc = Error#36d64342 },
{ 5a8745c1967adabe9d492d3595f37ce1 = Error#39ba5a14 }
]
}
Then take each error element of the Map and set their id to be the same as their key. And add them into a List
List<Map<String, Error>> errorsMap = map.get("error");
List<Error> errors = new ArrayList<>();
for(Map<String, Error> errorMap : errorsMap) {
String key = new ArrayList<>(errorMap.keySet()).get(0);
Error error = errorMap.get(key);
error.setId(key);
errors.add(error);
}
errors.forEach(System.out::println);
Outputs:
id=fea09b93175b626e4bb3d248ccb890bc, name=80_5595_10.zip (5.0), error=[Location path does not exist]
id=5a8745c1967adabe9d492d3595f37ce1, name=80_7208_01.zip (5.0), error=[Location path does not exist]

Add Map Values to a JSON object in identical key field names

I have the following Java Map. Map<String, String> containing values such as:
876234876, google
mike#hotmail, hotmail
9879892, google
I need to convert it to the following JSON object structure and Java JSON objects are not my friend.
"addresses" : [
{ "address":"876234876", "domain":"google" },
{ "address":"mike#hotmail", "domain":"hotmail" },
{ "address":"9879892", "domain":"google" }
]
To create the JSON you ask, you need to insert a JSONObject into a JSONArray. So for each Entry of your Map<String, String>, create a JSONObject like {"address": entry.key, "domain": entry.value} and add those to a JSONArray.
Let's use a Stream.map to create that object and insert the result into the array directly:
public static JSONObject createJson(Map<String, String> value) {
JSONObject result = new JSONObject();
JSONArray addresses = new JSONArray();
result.put("addresses", addresses);
value.entrySet().stream() //iterate the map
.map(e -> { //build an object
JSONObject address = new JSONObject();
address.put("address", e.getKey());
address.put("domain", e.getValue());
return address;
})
.forEach(addresses::put); //insert into the array
return result;
}
And test it with :
public static void main(String[] args) {
Map<String, String> values = new HashMap<>();
values.put("876234876", "google");
values.put("mike#hotmail", "hotmail");
values.put("9879892", "google");
System.out.println(createJson(values).toString(4));
}
And the result :
{"addresses": [
{
"address": "9879892",
"domain": "google"
},
{
"address": "876234876",
"domain": "google"
},
{
"address": "mike#hotmail",
"domain": "hotmail"
}
]}
Using the API : JSON In Java
<!-- https://mvnrepository.com/artifact/org.json/json -->
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
Check this solution:
List<String> addresses = new ArrayList<>();
map.forEach((k, v) -> {
Map<String, String> nn = new HashMap<>();
nn.put("address", k);
nn.put("domain", v);
addresses.add(JSONValue.toJSONString(nn));
});
JSONObject result = new JSONObject(Collections.singletonMap("addresses", new JSONArray(addresses)));
Your JAVA objects should look like this :
List of addresses
#XmlRootElement
public class Foo {
private List<Address> addresses;
// Getter, Setter, ...
}
Address
public class Address {
private String address;
private String domain;
// Getters, setters, ...
}

Iterate hashmap's mongodb result in Freemarker

I am new at java and mongodb, and i dont see how to solve this, i have a collection:
{
"_id" : "20minutos",
"active" : true,
"group" : "20 Minutos",
"domains" : [
"20minutos.com",
"20minutos.es",
"20minutos.tv"
]
}
java code:
get("/pages/:page", (request, response) -> {
String page = request.params(":page");
if(page.equals("forms")){
UserDAO userDao = new UserDAO(Connection.getInstance().getDataStore());
HashMap<String,Object> map = new HashMap<String,Object>();
map.put("users", userDao.AllUsers());
return new ModelAndView(map, page+".ftl");
}else{
return new ModelAndView(null, page+".ftl");
}
}, new FreeMarkerEngine());
my AllUsers() function
public List<User> AllUsers() throws Exception{
return this.find().asList();
}
the pojo clas, the domains
public List<String> getDomains() {
return domains;
}
and the freemarker code
<#list users as data>
<tr class="odd gradeX">
<td>${data._id}</td>
<td>${data.active?string('yes', 'no')}</td>
<td>${data.group}</td>
<#assign x = ''>
<#assign keys = data?keys>
<#list keys as key>
<#assign x = x+','+key>
</#list>
<td>${x}</td>
</tr>
the problem is that i cant acces the values of Domains
i hope u someone can help me
thank you in advance
If you want to list user domains you can use join:
<td>${data.domains?join(",")}</td>

How to insert data in couchbase lite android in JSON format

I'm new to NoSQL databases. I want to save the following JSON data into CouchBase Lite. Can someone guide me on the best way to do this?
{"widget": {
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
"text": {
"data": "Click Here",
"size": 36,
"style": "bold",
"name": "text1",
"hOffset": 250,
"vOffset": 100,
"alignment": "center",
"onMouseUp": "sun1.opacity = (sun1.opacity / 100) * 90;"
}
}}
I tried to do this using the following code.
public void insertSample(String widget,String control,ArrayList<eModel> details){
Map<String, Object> properties = new HashMap<String, Object>();
properties.put("control", control);
properties.put("details", details);
Document document = database.getDocument(widget);
try {
document.putProperties(properties);
} catch (CouchbaseLiteException e) {
Log.e("", "Cannot save document", e);
}
}
But this code is creating a new id each time. I want to insert the same widget value in multiple times.
This is run time data, not static data I want to insert one by one.
For example, given a widget Map as follows:
{"widget": {
"window": {
"title": "Sample Konfabulator Widget",
"name": "main_window",
"width": 500,
"height": 500
},
}
then I want to append the following field under the "window" field:
"image": {
"src": "Images/Sun.png",
"name": "sun1",
"hOffset": 250,
"vOffset": 250,
"alignment": "center"
},
}
The constraint on documents in Couchbase Lite is that the _id property should be unique. As the document gets updated, it creates new revisions.
There are two possible methods to update a document:
putProperties: given a new JSON object, it replaces the document's body with that object.
update: takes a callback function or block. It loads the current revision's properties, then calls this function, passing it an UnsavedRevision object, whose, properties are a mutable copy of the current ones. Your callback code can modify this object's properties as it sees fit; after it returns, the modified revision is saved and becomes the current one.
So, to update a widget document with the image dictionary, you should use the update method:
final Map<String, Object> imageProperties = new HashMap<String, Object>();
imageProperties.put("src", "Images/Sun.png");
imageProperties.put("name", "sun1");
// ...
Document document = database.getDocument(widgetId);
document.update(new Document.DocumentUpdater() {
#Override
public boolean update(UnsavedRevision newRevision) {
Map<String, Object> properties = newRevision.getUserProperties();
properties.put("image", imageProperties);
newRevision.setUserProperties(properties);
return true;
}
});
Note: It's recommended to use a library like Jackson to serialize/deserialize the JSON and POJO models in a Java application (you can read this blog post to find more info).
You need to construct your map like this to save like above json format.
Map<String, Object> windowMap = new HashMap<String, Object>();
windowMap.put("title","Sample Konfabulator Widget");
windowMap.put("name","main_window");
windowMap.put("width",500);
windowMap.put("height",500);
Map<String, Object> imageMap = new HashMap<String, Object>();
imageMap.put("src","Images/Sun.png");
imageMap.put("name","sun1");
imageMap.put("hOffset",250);
imageMap.put("vOffset",250);
Map<String, Object> textMap = new HashMap<String, Object>();
textMap.put("data","Click Here");
textMap.put("size",36);
Map<String, Object> memberMap = new HashMap<String, Object>();
memberMap.put("window",windowMap);
memberMap.put("image",imageMap);
memberMap.put("text",textMap);
Map<String, Object> widgetMap = new HashMap<String, Object>();
widgetMap.put("widget",memberMap);
try {
document.putProperties(widgetMap);
} catch (CouchbaseLiteException e) {
Log.e("", "Cannot save document", e);
}
I was having the same problem. You need to traverse the keys of the json and add each object using putproperties. However, for a JSONArray, you need to use an ArrayList. I am traversing the keys using the Jackson library(which is also used by couchbase internally)
try {
Map<String, Object> properties = new HashMap<String, Object>();
JsonFactory factory = new JsonFactory();
ObjectMapper mapper = new ObjectMapper(factory);
// convert you json string to Jackson JsonNode
JsonNode rootNode = mapper.readTree(doc.toString());
Iterator<Map.Entry<String, JsonNode>> it = rootNode.getFields();
while (it.hasNext()) {
Map.Entry<String, JsonNode> pair = it.next();
String key = pair.getKey().toString();
String value = pair.getValue().toString();
if (JSONDiffUtil.isJSONArray(value)) {
Debug.logInfo("its a json array: " + key, MODULE);
ArrayNode arrNode = (ArrayNode) pair.getValue();
properties.put(key, arrNode);
}
else if (key.startsWith("_")) {
Debug.logInfo("skipping _rev" + key, MODULE);
}
else {
Debug.logInfo("its a json object: " + key, MODULE);
properties.put(key, pair.getValue());
}
}
document.putProperties(properties);
}
catch (CouchbaseLiteException e) {
Debug.logInfo("Error", MODULE);
Debug.logInfo(e.getMessage(), MODULE);
} catch (JsonProcessingException e) {
Debug.logInfo(e.getMessage(), MODULE);
} catch (IOException e) {
Debug.logInfo(e.getMessage(), MODULE);
}
There is a very useful link where you can find good info
https://blog.couchbase.com/object-mapping-couchbase-mobile-android/

Categories

Resources