Create hashmap with arraylist of hashmap - java

I have the following structure
{
"abc":[
{
"bc":"52",
"gd":"jjksa"
}
]
}
Now I need to create the same structure from the client side and send the data similar like the above format. I am assuming the structure to be something like this.
HashMap<String, ArrayList<HashMap<String, String>>> hashmap = new HashMap<String, ArrayList<new HashMap<String, String>()>>();
HashMap<String, String> obj1 = new HashMap<String, String>();
ArrayList<String> arraylist = new ArrayList<String>();
obj1.put("bc", "52");
obj1.put("gd", "jjksa");
arraylist.add(obj1);
hashmap.put("metrics", arraylist)
Anyone who can help me create the proper map as shown in the above example.

Use a JSON processor such as Jackson:
import org.codehaus.jackson.map.ObjectMapper;
// ...
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(hashmap);

The below code worked for me. However the suggestion that you guys have put forward is surely valuable. I will make the changes accordingly to make the structure better.
HashMap<String, Object> hashmap = new HashMap<String, Object>();
HashMap<String, String> obj1 = new HashMap<String, String>();
ArrayList arraylist = new ArrayList();
obj1.put("bc", "52");
obj1.put("gd", "jjksa");
arraylist.add(obj1);
hashmap.put("metrics", arraylist);
Gson json = new Gson();
System.out.print(json.toJson(hashmap));

Simple the HashMap's toString method prints the value excatly like your json but without the double-quotes("). :)
sp00m's answer works perfectly. In addition to that you could also use google's Gson.
import java.util.ArrayList;
import java.util.HashMap;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
public class GsonParser {
public static void main(String[] args) throws Exception {
HashMap<String, ArrayList<HashMap<String, String>>> hashmap = new HashMap<String, ArrayList<HashMap<String, String>>>();
HashMap<String, String> obj1 = new HashMap<String, String>();
ArrayList<HashMap<String, String>> arraylist = new ArrayList<HashMap<String, String>>();
obj1.put("bc", "52");
obj1.put("gd", "jjksa");
arraylist.add(obj1);
//Hashmap toString
hashmap.put("metrics", arraylist);
System.out.println(hashmap); //Prints : {metrics=[{bc=52, gd=jjksa}]}
//Jackson Example
ObjectMapper mapper = new ObjectMapper();
String json = mapper.writeValueAsString(hashmap);
System.out.println(json); //Prints : {"metrics":[{"bc":"52","gd":"jjksa"}]}
//Gson Example
Gson gson = new Gson();
String json2 = gson.toJson(hashmap);
System.out.println(json2); //Prints : {"metrics":[{"bc":"52","gd":"jjksa"}]}
}
}

Related

Cannot resolve method 'entry' in 'Map'

I am using this class to manipulate some data using Java:
private static Set<Entry<String, String>> flatten(Map<String, List<String>> map) {
return map.entrySet().stream().flatMap(e ->
e.getValue().stream().map(v -> Map.entry(e.getKey(), v))
)
.collect(Collectors.toSet());
}
However, when I try to compile on eclipse/intellij, I am getting this error:
Cannot resolve method 'entry' in 'Map'
As you can see on the code below, everything is working fine:
https://www.online-java.com/4LblEuqTN6
My code on eclipse is the following:
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map.*;
import java.util.Set;
import java.util.stream.Collectors;
#RestController
#RequestMapping(value="test")
public class HelloController extends BaseExtController {
private static Set<Entry<String, String>> flatten(Map<String, List<String>> map) {
return map.entrySet().stream().flatMap(e ->
e.getValue().stream().map(v -> Map.entry(e.getKey(), v))
)
.collect(Collectors.toSet());
}
private static Map<String, List<String>> group(Set<Map.Entry<String, String>> entries) {
return entries.stream().collect(Collectors.groupingBy(
Map.Entry::getKey, Collectors.mapping(Map.Entry::getValue, Collectors.toList())
));
}
#RequestMapping (value="sync", method = RequestMethod.GET
, produces=MediaType.APPLICATION_JSON_VALUE)
public Map<String, List<String>> syncForms(
Model model,
HttpServletRequest request,
HttpServletResponse response) throws Exception {
Map<String, List<String>> dictOP = new HashMap<String, List<String>>();
Map<String, List<String>> dictMobile = new HashMap<String, List<String>>();
List<String> obj1Mobile = new ArrayList<String>();
List<String> obj1Op = new ArrayList<String>();
obj1Mobile.add("Argentina");
obj1Op.add("Argentina");
dictOP.put("obj1", obj1Op);
dictMobile.put("obj1", obj1Mobile);
Set<Entry<String, String>> mobileEntries = flatten(dictMobile);
Set<Entry<String, String>> opEntries = flatten(dictOP);
Set<Entry<String, String>> add = new HashSet<>(opEntries);
add.removeAll(mobileEntries);
Set<Entry<String, String>> remove = new HashSet<>(mobileEntries);
remove.removeAll(opEntries);
return group(add);
}
Do you guys know why this is happening ? Am I defining some wrong type ?

Parsing the openweatherMap json file

I am working on a project,which requires to get weather information and so i used openweathermap api. My program worked and i got information from "main" and "wind" ,but i also need to get description from the main weather set.The problem is that the weather set is a list in the json file and i am unable to cast it to map.The example json file which i am trying to parse is http://api.openweathermap.org/data/2.5/weather?q=London
JSON:
{
"coord":{
"lon":-0.13,
"lat":51.51
},
"weather":[
{
"id":803,
"main":"Clouds",
"description":"broken clouds",
"icon":"04n"
}
],
"base":"stations",
"main":{
"temp":43.56,
"pressure":1004,
"humidity":87,
"temp_min":41,
"temp_max":46.4
},
"visibility":10000,
"wind":{
"speed":11.41,
"deg":80
},
"rain":{
},
"clouds":{
"all":75
},
"dt":1573350303,
"sys":{
"type":1,
"id":1414,
"country":"GB",
"sunrise":1573369754,
"sunset":1573402780
},
"timezone":0,
"id":2643743,
"name":"London",
"cod":200
}
When we look at the file,we notice that there is an [] bracket inside the weather set which is creating problems in my project.I tried to look up on how to cast list to map and tried playing with my code ,but didn't help.The commented code in the file are things which i have tried while trying to make it work.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.URL;
import java.net.URLConnection;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.*;
import com.google.gson.reflect.*;
import java.util.List;
import java.lang.reflect.Type;
import java.util.HashMap;
import java.util.Map;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
public class PlantWateringApp {
public static Map<String, Object> jsonToMap(String str) {
Map<String, Object> map = new Gson().fromJson(str, new TypeToken<HashMap<String, Object>>() {
}.getType());
return map;
}
public static void main(String[] args) {
String LOCATION = "delhi,india";
String result = "{\"coord\":{\"lon\":77.22,\"lat\":28.65},\"weather\":[{\"id\":711,\"main\":\"Smoke\",\"description\":\"smoke\",\"icon\":\"50d\"}],\"base\":\"stations\",\"main\":{\"temp\":72.32,\"pressure\":1015,\"humidity\":59,\"temp_min\":64.4,\"temp_max\":77},\"visibility\":1000,\"wind\":{\"speed\":3.36,\"deg\":270},\"clouds\":{\"all\":0},\"dt\":1573351180,\"sys\":{\"type\":1,\"id\":9165,\"country\":\"IN\",\"sunrise\":1573348168,\"sunset\":1573387234},\"timezone\":19800,\"id\":1273294,\"name\":\"Delhi\",\"cod\":200}";
System.out.println(result);
Map<String, Object> respMap = jsonToMap(result.toString());
Map<String, Object> mainMap = jsonToMap(respMap.get("main").toString());
Map<String, Object> windMap = jsonToMap(respMap.get("wind").toString());
// Type listType = new TypeToken<List<Map<String,String>>>()
// {}.getType();
// List<Map<String,String>> weatherMap = new
// Gson().fromJson(respMap.get("description").toString(),listType);
// Map<String, Object> name = (Map<String, Object>)
// respMap.get("description");
// Map<String, Object > weatherMap = jsonToMap
// (respMap.get("description").toString());
System.out.println("Location: " + LOCATION);
System.out.println("Current Temperature: " + mainMap.get("temp"));
System.out.println("Current Humidity: " + mainMap.get("humidity"));
System.out.println("Max: " + mainMap.get("temp_min"));
System.out.println("Min: " + mainMap.get("temp_max"));
System.out.println("Wind Speed: " + windMap.get("speed"));
System.out.println("Wind Angle: " + windMap.get("deg"));
}
}
I tried to do the same way as i did for main and wind : Map weatherMap = jsonToMap (respMap.get("weather").toString()); .But i got errors:
////java.lang.IllegalStateException: Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 3 path $[0]
So i tried to not convert json to Map rather directly use map like Map weatherMap = (Map) respMap.get("weather"); but i got
////java.lang.ClassCastException: java.util.ArrayList cannot be cast to java.util.Map
For this,i tried to cast list to map using
List<Map<String,String>> weatherMap = new Gson().fromJson(respMap.get("weather").toString(),listType);
But this says:
//String cannot be converted to int
I am really confused on what to do in this situation.I am unable to figure out how to deal with [] in the json file.
As this data is provided as a List and you are trying to convert it into the Map. That is not right. You need to get it (weather) as a list of Map and then need to treat each element as Map. Here is an example how to get it as a Map
///...
//// other code
///...
Map<String, Object > respMap = jsonToMap (result.toString());
// don't need to convert from string to map again and again
Map<String, Object > mainMap = (Map<String, Object >)respMap.get("main");
Map<String, Object > windMap = (Map<String, Object >)respMap.get("wind");
// fist get weather as list
List<Map<String, Object >> weather = (List<Map<String, Object>>) (respMap.get("weather"));
//...
System.out.println("Wind Speed: " + windMap.get("speed") );
System.out.println("Wind Angle: " + windMap.get("deg") );
// weather as list
System.out.println("Weather: "+ weather);
// assuming weather contains at-least 1 element.
Map<String, Object> weatherMap = weather.get(0);
System.out.println("Weather as map: "+ weatherMap);
Casting it to list.
List<Map<String, Object >> weather = (List<Map<String, Object>>) (respMap.get("weather"));
Then treat each element as Map:
// assuming weather contains at-least 1 element.
Map<String, Object> weatherMap = weather.get(0);
Hope this helps.
Make life simple and use real types.
import java.util.List;
import com.google.gson.Gson;
public class PlantWateringApp {
class Weather_2_5 {
List<Weather> weather;
}
class Weather {
Integer id;
String main;
String description;
String icon;
}
public static void main(String[] args) {
String result = "{\"coord\":{\"lon\":77.22,\"lat\":28.65},\"weather\":[{\"id\":711,\"main\":\"Smoke\",\"description\":\"smoke\",\"icon\":\"50d\"}],\"base\":\"stations\",\"main\":{\"temp\":72.32,\"pressure\":1015,\"humidity\":59,\"temp_min\":64.4,\"temp_max\":77},\"visibility\":1000,\"wind\":{\"speed\":3.36,\"deg\":270},\"clouds\":{\"all\":0},\"dt\":1573351180,\"sys\":{\"type\":1,\"id\":9165,\"country\":\"IN\",\"sunrise\":1573348168,\"sunset\":1573387234},\"timezone\":19800,\"id\":1273294,\"name\":\"Delhi\",\"cod\":200}";
//System.out.println(result);
Gson G = new Gson();
Weather_2_5 obj = G.fromJson(result, Weather_2_5.class);
for (int idx = 0; idx < obj.weather.size(); idx++) {
System.out.println(obj.weather.get(idx).description);
}
}
}
Instead of writing it all from the beginning you could use:
https://github.com/xSAVIKx/openweathermap-java-api
I think this example is closest to what you are trying to do:
https://github.com/xSAVIKx/openweathermap-java-api/blob/development/api-examples/src/main/java/org/openweathermap/api/example/CurrentWeatherOneLocationExample.java

Convert JSON record to LinkedHashMap<String,String> using Jackson API

I have a JSON file(it contains an array of JSON objects.)
I am trying to read it object by object.
Each object I need to convert it to a LinkedHashMap<String,String> where both the key and value are strings. Note that even if the JSON objects contain a non-string value(Integer/Boolean), I want my LinkedHashMap to contain a string.
This is my JSON file (films.json):
[
{
"name": "Fight Club",
"year": 1999,
}
]
Now, this has 1 object. I want to convert it to a LinkedHashMap<String,String>.
So for the above example, my LinkedHashMap should contain(for the 1st JSON object) :
"name" : "Fight CLub"
"year" : "1999"
Notice how the year is String in the LinkedHashMap and not Integer.
This is what I tried.
Map<String, Object> myLinkedHashMap;
JsonParser jsonParser = new JsonFactory().createParser(new File("films.json"));
jsonParser = new JsonFactory().createParser(new File(filePath));
jsonParser.nextToken();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
while(jsonParser.nextToken() != JsonToken.END_ARRAY){
myLinkedHashMap = mapper.readValue(jsonParser, LinkedHashMap.class);
}
The variable myLinkedHashMap will contain a key/value pair for an object in my JSON file.
But the problem is that for 'year' of the JSON file, I am getting Integer in the LinkedHashMap as the JSON file also contains Integer.
Instead, I want the Integer as String in the LinkedHashMap.
Please help me get String in the LinkedHashMap instead of Integer.
Note: The solution should be generic to other data types also.
So if the JSON object contains boolean true, then my LinkedHashMap should contain "true".
You can construct map type using TypeFactory and constructMapType method to tell exactly what do you need from readValue method. See below example:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.type.MapType;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import org.springframework.util.Assert;
import java.io.File;
import java.util.LinkedHashMap;
public class JsonMapApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
ObjectMapper mapper = new ObjectMapper();
mapper.registerModule(new JavaTimeModule());
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
JsonParser jsonParser = mapper.getFactory().createParser(jsonFile);
jsonParser.nextToken();
MapType mapType = mapper.getTypeFactory().constructMapType(LinkedHashMap.class, String.class, String.class);
while (jsonParser.nextToken() != JsonToken.END_ARRAY) {
LinkedHashMap<String, String> map = mapper.readValue(jsonParser, mapType);
map.forEach((k, v) -> {
Assert.isInstanceOf(String.class, v);
System.out.println(k + " -> " + v + " (" + v.getClass().getName() + ")");
});
}
}
}
Above code prints:
name -> Fight Club (java.lang.String)
year -> 1999 (java.lang.String)
Change
Map<String, Object> myLinkedHashMap;
to
Map<String, String> myLinkedHashMap;

JSON containing ArrayList and HashMap

My servlet has an ArrayList and a HashMap object that I want to be sent to my jsp via AJAX. How do I do that and then how do I separate them out after getting them as javascript responseText? (Cant use jQuery)
ArrayList al = new ArrayList();
String json1= new Gson().toJson(al);
HashMap hm = new HashMap();
String json2= new Gson().toJson(hm);
What I havedone so far
ServletOutputStream os = res.getOutputStream();
String json = "[" + json1 + "," + json2 + "]";
System.out.println(json);
os.write(json.toString().getBytes());
flushCloseOutputStream(os);
res.setStatus(HttpServletResponse.SC_OK);
And then on jsp side
var jsonResponse = JSON.parse(this.responseText);
var workDesc = jsonResponse[1];
var thirdPartyData = jsonResponse[0];
My question is, is this the correct way of sending response?
GSON will do the trick. A simple example:
import java.lang.reflect.Type;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import java.util.HashMap;
class App {
private static final Type hashMapStringApp = new TypeToken<HashMap<String,App>>(){}.getType();
private String attribute;
public App(String attribute) {
this.attribute = attribute;
}
public static void main(String[] args) {
Gson gson = new Gson();
// Complex object to JSON
HashMap<String, App> map = new HashMap<>();
map.put("1", new App("Attr1"));
map.put("2", new App("Attr2"));
String json = gson.toJson(map);
System.out.println(json);
// JSON to complex object
HashMap<String, App> fromJson = gson.fromJson(json, hashMapStringApp);
System.out.println(fromJson.get("2").getAttribute());
}
public void setAttribute(String attribute) {
this.attribute = attribute;
};
public String getAttribute(){
return this.attribute;
}
}
Maven dependency:
<dependency>
<groupId>com.google.code.gson</groupId>
<artifactId>gson</artifactId>
<version>2.8.2</version>
</dependency>

How do I map to HashMap for array?

I have a JSON I want a to convert it to a HashMap. I have the following code -
ObjectMapper mapper = new ObjectMapper();
Map<String, String> jsonData = new HashMap<String, String>();
jsonData = mapper.readValue(userPropertyJson, new TypeReference<HashMap<String,String>>(){});
it is working fine if the input JSON is
{"user":1, "entity": "email"}
but fails when the JSON is as below -
{"user":1, "entity": ["email","fname","lname","phone"]}
How do I map to HashMap for array also?
Declare a generic HashMap with String as a key and Object as a value , since you don't know the type of value exactly.
Map<String, Object>
And beware of assigning wrong types while retrieving data
Use Map<String, Object>. Example
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
public class JacksonParser {
public static void main(String[] args) {
String userPropertyJson = "{\"user\":1, \"entity\": [\"email\",\"fname\",\"lname\",\"phone\"]}";
ObjectMapper mapper = new ObjectMapper();
try {
Map<String, Object> jsonData = new HashMap<String, Object>();
jsonData = mapper.readValue(userPropertyJson, new TypeReference<HashMap<String,Object>>(){});
System.out.println(jsonData);
} catch (JsonParseException e) {
System.out.println(e.getMessage());
} catch (JsonMappingException e) {
System.out.println(e.getMessage());
} catch (IOException e) {
System.out.println(e.getMessage());
}
}
}
If you know in advance that your json will always have the same format (a String key mapped to a List<String>, either with a single element or with many elements), then you could use the ACCEPT_SINGLE_VALUE_AS_ARRAY deserialization feature:
ObjectMapper mapper = new ObjectMapper()
.enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY);
String jsonWithArray =
"{\"user\": 1, \"entity\": [\"email\", \"fname\", \"lname\", \"phone\"]}";
Map<String, List<String>> map1 =
mapper.readValue(
jsonWithArray,
new TypeReference<HashMap<String, List<String>>>() {});
System.out.println(map1); // {user=[1], entity=[email, fname, lname, phone]}
String jsonWithoutArray = "{\"user\": 1, \"entity\": \"email\"}";
Map<String, List<String>> map2 =
mapper.readValue(
jsonWithoutArray,
new TypeReference<HashMap<String, List<String>>>() {});
System.out.println(map2); // {user=[1], entity=[email]}
This enables you to either have an array for the values in your json, or a single element.
Check out http://www.jsonschema2pojo.org/
It allows you to convert json to java object automatically. I use it when I need to create DTOs from a web service for which I don't have java mapping or SDK.

Categories