How to parse query param effectively in java? - java

All I have is the request URI from which I have to parse the query params. What I'm doing is adding them to json/hashmap and fetching again like the following
String requestUri = "name=raju&school=abcd&college=mnop&color=black&fruit=mango";
All I have to do is to finally assign it to variables like the following
String name = "raju";
String school = "abcd";
String college = "mnop";
String color = "black";
String fruit = "mango";
So I am parsing the request uri like the following
String[] paramsKV = requestUri.split("&");
JSONArray jsonKVArr = new JSONArray();
for (String params : paramsKV) {
String[] tempArr = params.split("=");
if(tempArr.length>1) {
String key = tempArr[0];
String value = tempArr[1];
JSONObject jsonObj = new JSONObject();
jsonObj.put(key, value);
jsonKVArr.put(jsonObj);
}
}
The another way is to populate the same in hash map and obtain the same. The other way is to match the requestUri string with regex pattern and obtain the results.
Say for an example to get the value of school I have to match the values between the starting point of the string school and the next & - which doesn't sound good.
What is the better approach to parse the query String in java?
How could i handle the following thing in a better way?
I need to construct another hash map like the following from the above results like
Map<String, String> resultMap = new HashMap<String, String>;
resultMap.put("empname", name);
resultMap.put("rschool", school);
resultMap.put("empcollege", college);
resultMap.put("favcolor", color);
resultMap.put("favfruit", fruit);
To make it simple all I have to do is to parse the query param and construct a hashMap by naming the key filed differently. How could I do it in a simple way? Any help in this is much appreciated.

Short answer: Every HTTP Client library will do this for you.
Example: Apache HttpClient's URLEncodedUtils class
String queryComponent = "name=raju&school=abcd&college=mnop&color=black&fruit=mango";
List<NameValuePair> params = URLEncodedUtils.parse(queryComponent, Charset.forName("UTF-8"));
They're basically approaching it the same way. Parameter key-value pairs are delimited by & and the keys from the values by = so String's split is appropriate for both.
From what I can tell however your hashmap inserts are mapping new keys to the existing values so there's really no optimization, save maybe for moving to a Java 8 Stream for readability/maintenance and/or discarding the initial jsonArray and mapping straight to the hashmap.

Here is another possible solution:
Pattern pat = Pattern.compile("([^&=]+)=([^&]*)");
Matcher matcher = pat.matcher(requestUri);
Map<String,String> map = new HashMap<>();
while (matcher.find()) {
map.put(matcher.group(1), matcher.group(2));
}
System.out.println(map);

You can use Java 8 and store your data in HashMap in one operation.
Map<String,String> map = Pattern.compile("\\s*&\\s*")
.splitAsStream(requestUri.trim())
.map(s -> s.split("=", 2))
.collect(Collectors.toMap(a -> a[0], a -> a.length > 1 ? a[1]: ""));

You can do it by Jersey library (com.sun.jersey.api.uri.UriComponent or org.glassfish.jersey.uri.UriComponent class):
String queryComponent = "name=raju&school=abcd&college=mnop&color=black&fruit=mango";
MultivaluedMap<String, String> params = UriComponent.decodeQuery(queryComponent, true);

Use jackson json parser. Maven dependency:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.5.3</version>
</dependency>
Now use ObjectMapper to create Map from json string:
ObjectMapper mapper = new ObjectMapper();
Map list = mapper.readValue(requestUri, Map.class);

Related

String to map conversion java

Code:
Map test = new HashMap<String,String>();
test.put("1", "erica");
test.put("2", "frog");
System.out.println(test.toString());
This code gives output as :
{1=erica, 2=frog}
I want this output to be again put in a map as key value-pair .
Any suggestions how can i implement this ?
Or is ther any predefined utility class for conversion of the output to HashMap again ?
For me a proper way would be to use a JSON parser like Jackson since the way a HashMap is serialized is not meant to be parsed after such that if you use specific characters like = or , they won't be escaped which makes it unparsable.
How to serialize a Map with Jackson?
ObjectMapper mapper = new ObjectMapper();
String result = mapper.writeValueAsString(myMap);
How to deserialize a String to get a Map with Jackson?
ObjectMapper mapper = new ObjectMapper();
Map map = mapper.readValue(contentToParse, Map.class);
You can try to use this:
String[] tk = mystring.split(" |=");
Map<String, String> map = new HashMap<>();
for (int i=0; i < tk.length-1; i++)
{
map.put(tk[i], tk[i]);
}
return map;
If you want to replicate the Java code filling the map, you may use something like this:
StringBuilder sb = new StringBuilder("Map<String, String> test = new HashMap<>();");
for(Map.Entry<?, ?> entry : test.entrySet())
{
sb.append("\ntest.put(\"");
sb.append(entry.getKey());
sb.append("\", \"");
sb.append(entry.getValue());
sb.append("\");");
}
String string = sb.toString();
System.out.println(string);
But I agree with the comments, that in many applications a format such as JSON is more appropriate to serialize a map.
Note that the above solution does not escape strings, it only works if the strings don't contain characters like " or \n. If you need to handle these cases it will become more complicated.
You could try the following:
String out = test.toString();
Map<String, String> newMap = new HashMap();
// remove the first and last "{", "}"
out = out.subString(1,out.size()-1)
String[] newOut = out.split(", ");
for (int i=0; i<newOut.length;i++){
// keyValue is size of 2. cell 0 is key, cell 1 is value
String[] keyValue = newOut.split("=");
newMap.put(keyValue[0], keyValue[1]);
}
I haven't tested the code in java i just wrote from my mind. I hope it will work

How to parse a uri with parameters into a Map in Java

I want to parse the following:
full_uri= "path/for/uri?$param1=value1&$param2=value2
in a way that gives me the uri as a string and the parameters as a map. What I'm trying right now is:
String[] full_uri_split = full_uri.split("\\?");
String uri = full_uri_split[0];
String parameters = full_uri_split[1];
This gives me 2 variables, 1 that is the uri, and another that is a string containing all the parameters, in the format of:
parameters = "$param1=value1&$param2=value2"
My next best guess is to then split it on the & signs:
String parameters_split = parameters.split("&");
which returns:
["$param1=value1", "$param2=value2"]
Now I want to convert this into a Map that looks like so:
"param1":"value1",
"param2":"value2"
and I'm not sure how to go about it.
I'm sure I could get it to work by doing more splits, but it seems horribly inefficient. So essentially, I want to turn:
full_uri = "path/for/uri?$param1=value1&$param2=value2"
into
uri = "path/for/uri"
params = {
"param1": "value1",
"param2": "value2"
}
Here is a solution using a loop.
Map<String, String> params = new HashMap<>();
for (String s : parameters_split){
params.put(s.split("=")[0], s.split("=")[1]);
}

Putting JSON values into Hashmap

I have JSON value like below,
{ "emp_id": 1017,
"emp_name": "karthik Y",
"emp_designation": "Manager",
"department": "JavaJson",
"salary": 30000,
"direct_reports":
[
"Nataraj G",
"Kalyan",
"Mahitha"
]
}
HashMap < String, String[] >input1 = new HashMap < String, String[] >();
input1.put("empid","1017");
input1.put("emp_name","karthik");
input1.put("emp_designation","manager");
input1.put("salary","30000");
now I want to add next array that is direct_report to put as next key and value(entire array shoud be come one key and value). Someone please help out.
Hashmap is a key/value storage, where keys are unique. You can convert your JSON to string and then store it as a value to the hashmap. For example something like below:
public static void main(String[] args) {
String json = "{ \"emp_id\": 1017,"
+ "\"emp_name\": \"karthik Y\","
+ "\"emp_designation\": \"Manager\","
+ "\"department\": \"JavaJson\","
+ "\"salary\": 30000,"
+ "\"direct_reports\": ["
+ "\"Nataraj G\","
+ "\"Kalyan\","
+ "\"Mahitha\"]}";
HashMap<String, String> jsonStore = new HashMap<String, String>();
jsonStore.put("myJson", json);
System.out.println(jsonStore.get("myJson"));
}
You need can also use the 'org.json' library to
Create JSON object manually
Convert existing JSONObject to String representation
Convert JSON string to JSONObject
You can also have the following solution:
JSONObject jsonObject = new JSONObject();
jsonObject.put("empt_id", 1017);
jsonObject.put("emp_name", "karthik");
HashMap<String, JSONObject> jsonObjectStore = new HashMap<String, JSONObject>();
jsonObjectStore.put("myJsonObject", jsonObject);
HashMap<JSONObject, String> jsonObjectStore2 = new HashMap<JSONObject, String>();
jsonObjectStore2.put(jsonObject, "myJson");
Make sure that you download the org.json jar file and put it in your classpath to be able to use the JSONObject. You can download the jar from here.
In order to put each of those values into map as single key/value entry. You have mentioned it yourself, it should work without any problem. See below methods:
Method 1
Everything in Java is Object, String inherits Object, String[] inherits object. You can have the following solution:
HashMap<String, Object> myObjectStore4 = new HashMap<String, Object>();
String[] directReports4 = new String[]{"Natraj G", "Kalyan", "Mahitha"};
myObjectStore4.put("emp_id", new String("123"));
myObjectStore4.put("emp_name", new String("Raf"));
// others ....
myObjectStore4.put("directReports", directReports4);
Method 2
To store the fields as key/value and if you can afford converting the array to String (which represents all array elements comma separated then use this method).
HashMap<String, String> myObjectStoreTwo = new HashMap<String, String>();
String[] directReports2 = new String[]{"Natraj G", "Kalyan", "Mahitha"};
myObjectStoreTwo.put("emp_id", "123");
myObjectStoreTwo.put("emp_name", "Raf");
myObjectStoreTwo.put("salary", "222");
//Converts array to comma separated String
myObjectStoreTwo.put("directReports",Arrays.toString(directReports2));
Method 3
In the expense of having Hash Map to store String key and Array value. You have to put other elements as array too.
HashMap<String, String[]> myObjectStore3 = new HashMap<String, String[]>();
String[] directReports3 = new String[]{"Natraj G", "Kalyan", "Mahitha"};
myObjectStore3.put("emp_id", new String[]{123 + ""});
myObjectStore3.put("salary", new String[]{32312 + ""});
myObjectStore3.put("directReports", directReports3);
Use a jackson ObjectMapper. Try if this works
String json = "{....}"
HashMap<String,Object> mappedVals = new ObjectMapper().readValue(
json ,
new TypeReference<HashMap<String,Object>>() {
});

How to append a String to JSON String in java?

I am getting the data from the Zookeeper node like this
byte[] bytes = client.getData().forPath("/my/example/node1");
String ss = new String(bytes);
Here ss will have data like this which is a simple JSON String consisting of key value pair -
{"description":"Some Text", "machinename":"machineA", "ipaddress":"192.128.0.0"}
Now I want to append one more key value pair at the end to the above JSON String. This is the below key value pair I want to append -
"version":"v3"
So the final JSON String will look like this -
{"description":"Some Text", "machinename":"machineA", "ipaddress":"192.128.0.0", "version":"v3"}
What's the best and efficient way to do this?
Use a JSON Parser/Generator to parse your given JSON to a tree structure and then add your JSON field.
With Gson, that would look something like this
Gson gson = new Gson();
JsonObject jsonObject = gson.fromJson(ss, JsonObject.class); // parse
jsonObject.addProperty("version", "v3"); // modify
System.out.println(jsonObject); // generate
prints
{"description":"Some Text","machinename":"machineA","ipaddress":"192.128.0.0","version":"v3"}
Will Zookeeper always return valid JSON or their custom format? Be aware of that.
When it comes to JSON processing, string manipulation only works in special and simple cases. For the general case, a good JSON parser library should be used.
Jackson is among the top of such libraries in terms of performance, efficiency, versatility and reliability, plus it is published under the commercial-friendly Apache 2.0 license.
Following is a simple implementation of the requested answer in Jackson.
public static void main(String[] args)
{
String ss = "{\"description\":\"Some Text\", \"machinename\":\"machineA\", \"ipaddress\":\"192.128.0.0\"}";
System.out.println("JSON string before: " + ss);
try
{
ObjectMapper mapper = new ObjectMapper();
Map<String, String> map = (Map<String, String>)mapper.readValue(ss, Map.class);
map.put("version", "v3");
ss = mapper.writeValueAsString(map);
}
catch (Exception e)
{
e.printStackTrace();
}
System.out.println("JSON string after: " + ss);
}
Basic string manipulation. Insert your additional string before the final close brace }. Make sure to add a comma.
Json objects don't need to be ordered.
String json = "{\"key1\":\"value1\",\"key2\":\"value2\"}";
String json2 = "\"version\":\"v3\"";
json2 = ',' + json2;
String json3 = json.substring(0,json.length()-1) + json2 + json.charAt(json.length()-1);
That should be the simplest, most efficient way, if that's all you need to do.
For additional reading on String manipulation,
http://docs.oracle.com/javase/tutorial/java/data/manipstrings.html

How to deserialize a jsonarray into a List<Map> in java using flexjson.deserializer?

In the client side, I have constructed a JSOnARRAY like this:
{"filterEntries":[{"dataName":"mainContact","filterValue":"BILLGATES"}]}.
On the server side (java), I can retireve the values using :
jfilter = JSONValue.parse(jsonFilterStr); //jsonFilterStr={"filterEntries":[{"dataName":"mainContact","filterValue":"BILLGATES"}]}.
JSONArray jFilterEntries = (JSONArray) jfilter.get("filterEntries");
for (int i=0;i<jFilterEntries.size();i++){
JSONObject jFilterEntry = (JSONObject) jFilterEntries.get(i);
String dataName = (String) jFilterEntry.get("dataName");
String filterValue = (String) jFilterEntry.get("filterValue");
}
But the existing app is using flex.json.deserializer and I am unable to achieve the same using flex.json.deserializer. How should I proceed?
I wish to do something like this:
JSONDeserializer jsonDeserializer = new JSONDeserializer();
jsonDeserializer.use(null, List.class);
List<Map<String,String>> lMap= (List<Map<String,String>>)jsonDeserializer.deserialize(params);
Remember the top object that wraps the array. You have to handle that as well. You have to tell it to expect a Map inside the List. To do that you have to specify the type contained in the list by using the path expression "values".
Map<String,List<Map<String,String>>> result = new JSONDeserializer<Map<String,List<Map<String,String>>>>()
.use("values",List.class)
.use("values.values", Map.class)
.deserialize( json);
List<Map<String,String>> filterEntries = result.get("filterEntries");
Updated: Add the new keyword, and made the generic types on the right match the left.

Categories