I want to parse a descriptive-style URL with slashes (such as server/books/thrillers/johngrisham/thefirm), in Java.
My overall idea is to handle the data I receive to do a lookup (therefore using the URL as search criteria) in a database and then return HTML pages with data on it.
How do I do this?
String urlToParse = "server/books/thrillers/johngrisham/thefirm";
String[] parsedURL = urlToParse.split("/");
What you will have is an array of strings that you can then work with.
// parsedURL[0] == "server";
// parsedURL[1] == "books";
// parsedURL[2] == "thrillers";
// parsedURL[3] == "johngrisham";
// parsedURL[4] == "thefirm";
The split() method of String class can do the work, as commented Ionut before.
Related
I need to replace substring from a given string with empty string with the substring appearing in different positions of the string.
I want to remove the "fruit":"apple" from these possible combinations of the strings and expected the corresponding string:
{"client":"web","fruit":"apple"} --> {"client":"web"}
{"fruit":"apple","client":"web"} --> {"client":"web"}
{"client":"web","fruit":"apple","version":"v1.0"} --> {"client":"web","version":"v1.0"}
{"fruit":"apple"} --> null or empty string
I used regexp_replace(str, "\,*\"fruit\"\:\"apple\"", "") but that didn't get me the expected results. What is the right way to construct the regex?
It seems that you are working with data in JSON format. Depending from included dependencies you can achieve it totally without regular expression.
For example, if you are using Google's lib Gson, then you can parse String to JsonObject and then remove property from it
String input = "your data";
JsonParser parser = new JsonParser();
JsonObject o = parser.parse(input).getAsJsonObject();
try {
String foundValue = o.getAsJsonPrimitive("fruit").getAsString();
if ("apple".equals(foundValue)) {
o.remove("fruit");
}
} catch (Exception e) {
e.printStackTrace();
}
String filteredData = o.toJSONString();
P.S. code is not final version, it might needs handling of some situations (when there is no such field, or it contains non-primitive value), need further details to cover it
P.P.S. IMO, using regex in such situatioins makes code less readable and flexible
I am working on an android project where it needs to get data from database as grid view (contains multiple buttons). I have already done up to that part. Now I need to compare those data with a given string.
Here, I have tagged the status from the database to the button before put it in to the grid view.
holder.btn.setTag(data.get(position).getStatus());
the following code has shown that how I am trying to compare those values.
String x = "NA";
String y = holder.btn.getTag().toString();
if (x.equals(y)) {
holder.btn.setEnabled(false);
}
But it is not working. Please Help me to solve this issue.
Additionally, in my database there is a column call status....it contains values such as A and NA (Available and Not Available). I have already got that values from data base and set it to the item objects array list call data. in that item object i have declared field call status and then I have assigned that data base values to that.
Thanks in advance.
The method getTag() returns an Object, not a String. So you have to cast it to a String when you retrieve it. Try this:
String x = "NA";
String y = (String) holder.btn.getTag();
if (x.equals(y)) {
holder.btn.setEnabled(false);
}
Also keep in mind that if you are originally setting the Tag with something other than a String, then you'll have to convert it to a String when you use getTag(). So, for example, if your line holder.btn.setTag(data.get(position).getStatus()); sets an int as the tag, you would have to do String y = (String) Integer.toString(holder.btn.getTag()); or something similar.
Maybe the problem is at line if getStatus() returns no string
holder.btn.setTag(data.get(position).getStatus());
You can try with
holder.btn.setTag(data.get(position).getStatus().toString());
I am trying to write a Spring REST Controller getting an array of strings as input parameter of a HTTP GET request.
The problem arises when in the GET request, in some of the strings of the array, I use special characters like commas ,, blank spaces or forward slash /, no matter if I URL encode the query part of the URL HTTP GET request.
That means that the string "1/4 cup ricotta, yogurt" (edit which needs to be considered as a unique ingredient contained as a string element of the input array) in either this format:
http://127.0.0.1:8080/[...]/parseThis?[...]&ingredients=1/4 cup ricotta, yogurt
This format (please note the blank spaces encoded as + plus, rather than the hex code):
http://127.0.0.1:8080/[...]/parseThis?[...]&ingredients=1%2F4+cup+ricotta%2C+yogurt
Or this format (please note the blank space encoded as hex code %20):
http://127.0.0.1:8080/[...]/parseThis?[...]&ingredients=1%2F4%20cup%20ricotta%2C%20yogurt
is not rendered properly.
The system does not recognize the input string as one single element of the array.
In the 2nd and 3rd case the system splits the input string on the comma and returns an array of 2 elements rather than 1 element. I am expecting 1 element here.
The relevant code for the controller is:
#RequestMapping(
value = "/parseThis",
params = {
"language",
"ingredients"
}, method = RequestMethod.GET, headers = HttpHeaders.ACCEPT + "=" + MediaType.APPLICATION_JSON_VALUE)
#ResponseBody
public HttpEntity<CustomOutputObject> parseThis(
#RequestParam String language,
#RequestParam String[] ingredients){
try {
CustomOutputObject responseFullData = parsingService.parseThis(ingredients, language);
return new ResponseEntity<>(responseFullData, HttpStatus.OK);
} catch (Exception e) {
// TODO
}
}
I need to perform HTTP GET request against this Spring controller, that's a requirement (so no HTTP POST can be used here).
Edit 1:
If I add HttpServletRequest request to the signature of the method in the controller, then I add a log statement like log.debug("The query string is: '" + request.getQueryString() + "'"); then I am seeing in the log a line like The query string is: '&language=en&ingredients=1%2F4+cup+ricotta%2C+yogurt' (So still URL encoded).
Edit 2:
On the other hand if I add WebRequest request to the signature of the method, the the log as log.debug("The query string is: '" + request.getParameter("ingredients") + "'"); then I am getting a string in the log as The query string is: '1/4 cup ricotta, yogurt' (So URL decoded).
I am using Apache Tomcat as a server.
Is there any filter or something I need to add/review to the Spring/webapp configuration files?
Edit 3:
The main problem is in the interpretation of a comma:
#ResponseBody
#RequestMapping(value="test", method=RequestMethod.GET)
public String renderTest(#RequestParam("test") String[] test) {
return test.length + ": " + Arrays.toString(test);
// /app/test?test=foo,bar => 2: [foo, bar]
// /app/test?test=foo,bar&test=baz => 2: [foo,bar, baz]
}
Can this behavior be prevented?
The path of a request parameter to your method argument goes through parameter value extraction and then parameter value conversion. Now what happens is:
Extraction:
The parameter is extracted as a single String value. This is probably to allow simple attributes to be passed as simple string values for later value conversion.
Conversion:
Spring uses ConversionService for the value conversion. In its default setup StringToArrayConverter is used, which unfortunately handles the string as comma delimited list.
What to do:
You are pretty much screwed with the way Spring handles single valued request parameters. So I would do the binding manually:
// Method annotations
public HttpEntity<CustomOutputObject> handlerMethod(WebRequest request) {
String[] ingredients = request.getParameterValues("ingredients");
// Do other stuff
}
You can also check what Spring guys have to say about this.. and the related SO question.
Well, you could register a custom conversion service (from this SO answer), but that seems like a lot of work. :) If it were me, I would ignore the declaration the #RequestParam in the method signature and parse the value using the incoming request object.
May I suggest you try the following format:
ingredients=egg&ingredients=milk&ingredients=butter
Appending &ingredients to the end will handle the case where the array only has a single value.
ingredients=egg&ingredients=milk&ingredients=butter&ingredients
ingredients=milk,skimmed&ingredients
The extra entry would need to be removed from the array, using a List<String> would make this easier.
Alternatively if you are trying to implement a REST controller to pipe straight into a database with spring-data-jpa, you should take a look at spring-data-rest. Here is an example.
You basically annotate your repository with #RepositoryRestResource and spring does the rest :)
A solution from here
public String get(WebRequest req) {
String[] ingredients = req.getParameterValues("ingredients");
for(String ingredient:ingredients ) {
System.out.println(ingredient);
}
...
}
This works for the case when you have a single ingredient containing commas
I have query string like that:
ObjectGUId=1abcde&ObjectType=2&ObjectTitle=maximumoflife&Content=racroi&TimeStamp=2012-11-05T17:20:06.056
And I have Java Object:
LogObject{
private String ObjectGUId;
private String ObjectType;
private String ObjectTitle;
private String Content;
private String TimeStamp;
}
So i want to parse this query string to this java Object.
I've searched and read many question but not gotten correct answer yet.
Show me what can solve this problem.
Inspired by #bruno.braga, here's a way using Apache http-components. You leverage all the parsing corner cases:
List<NameValuePair> params =
URLEncodedUtils.parse("http://example.com/?" + queryString, Charset.forName("UTF-8"));
That'll give you a List of NameValuePair objects that should be easy to work with.
If you do not really need to push the querystring into your own class (you might want that though), instead of parsing it manually, you could use the URLDecoder, as #Sonrobby has commented:
String qString = "ObjectGUId=1abcde&ObjectType=2&ObjectTitle=maximumoflife";
Uri uri = Uri.parse(URLDecoder.decode("http://dummy/?" + qString, "UTF-8"));
if (uri != null) {
for(String key: uri.getQueryParameterNames()) {
System.out.println("key=[" + key + "], value=[" + uri.getQueryParameter(key) + "]");
}
}
The "dummy" looks dirty but it is required if what you only have is the querystring values (qString). If you have the complete URL, just pass it directly to the URLDecoder, and you are done.
Etiquette
You really should be much more specific about what you have tried and why it didn't work.
A proper code sample of your LogObject would really be very helpful here.
Ideally, you would provide a SSCCE so others could easily test your problem themselves.
Answer
You can extract the name:value pairs like this:
String toParse = "ObjectGUId=1abcde&ObjectType=2&ObjectTitle=maximumoflife&Content=racroi&TimeStamp=2012-11-05T17:20:06.056";
String[] fields = toParse.split("&");
String[] kv;
HashMap<String, String> things = new HashMap<String, String>();
for (int i = 0; i < fields.length; ++i)
{
t = fields[i].split("=");
if (2 == kv.length)
{
things.put(kv[0], kv[1]);
}
}
I have chosen to put them into a HashMap, but you could just as easily look at the name part (kv[0]) and choose to do something with it. For example:
if kv[0].equals("ObjectGUId")
{
logObject.setGUId(kv[1]); // example mutator/setter method
}
else if //...
However, all your fields in LogObject are private and you haven't shown us any methods, so I hope you have some way of setting them from outside... bear in mind you will need to store the pairs in a data structure of some kind (as I have done with a HashMap) if you intend to intialise a LogObject with all the fields rather than setting the fields after a constructor call.
Speaking of SSCCEs, I made one for this answer.
LinkedIn rest API for people search has following format http://api.linkedin.com/people-search?search-param1=val1&search-param2=val2...
Since I intend to use this many time in my application, I am trying to create a Search object like this where we can set values for different search parameters and then a method called generateQueryUrl to generate the url in above format.
public class Search {
private String searchParam1;
private String searchParam2;
public void setSearchParam1(String val) { this.searchParam1 = val; }
public void setSearchParam2(String val) { this.searchParam2 = val; }
//Form the query url
public String generateQueryUrl(){
String url = "";
if(searchParam1 != null) {
url += "search-param1=" + searchParam1 + "&";
}
if(searchParam2 != null) {
url += "search-param2=" + searchParam2 + "&";
}
return url;
}
My question is, is there a better pattern/design to do this? If there are many parameters, checking for NULL and then appending corresponding parameter name, value seems to add redundant code to me.
Also please let me know if this approach is fine.
I think what you are designing is in fact a "Builder", in that you are building the URL that will be returned at the end. Think StringBuilder, or Apache's EqualsBuilder, HashCodeBuilder, etc.
For a more theoretical explanation, check http://sourcemaking.com/design_patterns/builder.
Now, as for your code, to properly build the URL, I would use "set" methods like you do, but inside them I would use Apache's HttpComponents (ex HttpClient) to properly append the parameters of the URL.
Think about it, if you insert a "&" in the value of one of the parameter, your query parameters will be messed up since you normally have to escape this character (and you don't seem to be doing it here). I prefer letting tested and known APIs (UriUtils) do that for me.
So, my class would look like so using Apache's HttpComponents:
public class SearchBuilder {
private URI baseUri;
private List<NameValuePair> parameters;
public SearchBuilder (URI baseUri) {
this.baseUri= baseUri;
this.parameters = new ArrayList<NameValuePair>();
}
public void addSearchParam1(String val) {
if(!StringUtils.isBlank(val)) {
parameters.add(new BasicNameValuePair("SearchParam1", val));
}
}
//Form the query url
public URI toURI(){
URI uri = URIUtils.createURI(baseUri.getScheme(), baseUri.getHost(), baseUri.getPort(), baseUri.getPath(), URLEncodedUtils.format(parameters, "UTF-8"), null);
return uri;
}
Edit: I added the "isBlank" check to ensure that parameters with null, empty of whitespace-only Strings will not be added to the query. Now, you can change that to check only for null, but I'm sure you got the idea.
You can maintain a Map with keys as the param names and values as the values. Your setter methods can put keys and values in the Map. Or, you can have one generic setter which accepts the name & the value.
In the generateQueryUrl method, you can just iterate over the Map.
You may also want to URLEncode the values if not being done at the later stage.