Java object to URL params - java

I have Java POJO object and my goal is to convert it to URL parameters and use it in POST method.
...
public class PayseraRequest {
private int projectid = 123;
private int orderid = 987;
private String accepturl = "http://www.test.com";
...
My goal is convert object PayseraRequest to String urlParams
urlParams -> projectid=123&orderid=987&http%3A%2F%2Fwww.test.com&...`

Yes, write a method to do this, but you should URLEncode each parameter. projectid and orderid do not need URLencoding but it doesn't hurt. accepturl must definitely be UrlEncoded. It is good practice to encode anything you want to put into the query string of a URL.
See https://docs.oracle.com/javase/7/docs/api/index.html?java/net/URLEncoder.html

you can override the toString method of that class and with a say so StringBuilder get what you need.

You can check an example I have here:
https://github.com/lmpampaletakis/datumBoxSpringMVC/tree/master/datumBoxSpringMVC/src/main/java/com/lebab/datumbox
Your answer might be at SendRequest.java
You can replace the values of each parameter you want from your pojo

Related

Convert annotation string to enum value with Jackson

I have an enum with #JsonProperty annotated:
public enum Type {
#JsonProperty("Files")
File,
#JsonProperty("Folders")
Folder,
}
I know I can deserialize a JSON string ({"fieldName":"Files"}) to get an object. But is there any way to convert the string annotated in #JsonProperty to enum value with Jackson like:
String s = "Files"
Type t = jackson.valueOf(s); // Type.File
Or can I achieve this:
Type t = Type.File;
String s = jackson.toString(t); // "Files"
I believe that a private String value can resolve this, but the code would have duplicated constants (too many "Files" and "Folders"). I wonder if Jackson or Gson has solution to achieve this.
It should just work with help of ObjectMapper
Type t = new ObjectMapper().readValue("\"Files\"", Type.class);
System.out.println(Type.File.equals(t)); //"true"
Please note that the String needs to be a valid JSON string, so it must contain the double quotes. The string content cannot be Files, but rather has to be "Files"
The other direction:
Type t = Type.File;
new ObjectMapper().writeValue(System.out, t); // "Files"
If I am understanding you correctly, then perhaps this is what you are looking for:
String annotationValueAsSTring = Type.class.getField(Type.File.name())
.getAnnotation(JsonProperty.class).value();
-- Edited --
To retrieve the Enum value from the #JsonProperty String value, then you will need to create a helper method:
public static <T extends Enum<T>> Optional<T> getEnumValueFromJsonProperty(Class<T> enumClass,
String jsonPropertyValue) {
Field[] fields = enumClass.getFields();
return Arrays.stream(fields).filter(field -> field.getAnnotation(JsonProperty.class).value().equals(jsonPropertyValue)).map(field -> Enum.valueOf(enumClass, field.getName())).findFirst();
}

How to add parameters in service call for #RequestParam backend?

If i have something like
#GetMapping(value = "/list")
public ResponseEntity<MyDTO> findStatusPerEC(#RequestParam final List<Long> numbersEC)
How do I add numbersEC in my url on the frontend? Is this query parameter?
I know this one was for old call that didnĀ“t had query parameters and data was only a number (long)
return this.http.get<any>(URL_API + '/simulator/status/' + data);
But now I have to send a list of long values...may you help me?
return this.http.get<any>(URL_API + '/simulator/status/' + data);
Since you mentioned data is only a long type, what you are referring to here when you make the above request is a PathVariable it is slightly different to a RequestParam.
Path variables have the syntax: /simulator/status/:statusID where statusID is dynamic and extracts values from the URI.
Request parameters have the syntax: ?arg=val&arg2=val2 etc... and extract values from the request query string.
Solution
To answer your question, to send an array across as request parameters, you can do it like so:
?myparam=myValue1&myparam=myValue2&myparam=myValue3
As you can see, above myparam is unchanging, and the values are variable, hence the data within your list data structure.
So when you're making your request it will look similar to this:
Angular/Javascript
return this.http.get<any>(URL_API + '/list' + '?myparam=myValue1&myparam=myValue2&myparam=myValue3');
Java
#GetMapping(value = "/list")
public ResponseEntity<MyDTO> findStatusPerEC(#RequestParam final List<Long> numbersEC)
I hope this helps.

Retrofit 2 - URL Query Parameter

I am using a query parameters to set the values needed by the Google Maps API.
The issue is I do not need the & sign for the first query parameter.
#GET("/maps/api/geocode/json?")
Call<JsonObject> getLocationInfo(#Query("address") String zipCode,
#Query("sensor") boolean sensor,
#Query("client") String client,
#Query("signature") String signature);
Retrofit generates:
&address=90210&sensor=false&client=gme-client&signature=signkey
which causes the call the fail when I need it to be
address=90210&sensor=false&client=gme-client&signature=signkey
How do I fix this?
If you specify #GET("foobar?a=5"), then any #Query("b") must be appended using &, producing something like foobar?a=5&b=7.
If you specify #GET("foobar"), then the first #Query must be appended using ?, producing something like foobar?b=7.
That's how Retrofit works.
When you specify #GET("foobar?"), Retrofit thinks you already gave some query parameter, and appends more query parameters using &.
Remove the ?, and you will get the desired result.
I am new to retrofit and I am enjoying it. So here is a simple way to understand it for those that might want to query with more than one query: The ? and & are automatically added for you.
Interface:
public interface IService {
String BASE_URL = "https://api.test.com/";
String API_KEY = "SFSDF24242353434";
#GET("Search") //i.e https://api.test.com/Search?
Call<Products> getProducts(#Query("one") String one, #Query("two") String two,
#Query("key") String key)
}
It will be called this way. Considering you did the rest of the code already.
Call<Results> call = service.productList("Whatever", "here", IService.API_KEY);
For example, when a query is returned, it will look like this.
//-> https://api.test.com/Search?one=Whatever&two=here&key=SFSDF24242353434
Link to full project: Please star etc: https://github.com/Cosmos-it/ILoveZappos
If you found this useful, don't forget to star it please. :)
public interface IService {
String BASE_URL = "https://api.demo.com/";
#GET("Login") //i.e https://api.demo.com/Search?
Call<Products> getUserDetails(#Query("email") String emailID, #Query("password") String password)
}
It will be called this way. Considering you did the rest of the code already.
Call<Results> call = service.getUserDetails("abc#gmail.com", "Password#123");
For example when a query is returned, it will look like this.
https://api.demo.com/Login?email=abc#gmail.com&password=Password#123

Design for large scale parameter validation for JPA?

I have a method that takes in a JSON and takes out the data and distributes it to various strings so that they can be set in an entity and persisted. My example below is quite simple but for my actual code I have about 20+ fields
For example see
public Projects createProject(JsonObject jsonInst) {
Projects projectInst = new Projects();
String pId = jsonInst.get("proId").getAsString();
String pName = jsonInst.get("proName").getAsString();
String pStatus = jsonInst.get("proStatus").getAsString();
String pCustId = jsonInst.get("proCustId").getAsString();
String pStartDate = jsonInst.get("proStartDate").getAsString();
...
//Set the entity data
projectInst.setProjectId(pId);
projectInst.setProjectName(pName);
...
Notice if a varible dosent have a corrosponding entry in the Json this code will break with null pointer exception. Obviously I need to validate each parameter befopre calling .getAsString()
What is the best way to do this from a readability point of view I could create 2 varibles for each parameter and check and set for example.
if(jsonInst.get("proName")){
String pName = jsonInst.get("proName").getAsString();
}
Or should I wait for it to be set
if(!pName.isEmpty()){
projectInst.setName(pName)
}
...
Which of these do you think is the best parameter to use for preventing errors.
Is there a way to handle if something is set on a large scale so that I can reduce the amount of code I have to write before I use that varible?
You can create a method that will take field name as parameter and will return json value for that field :
private String getJSONData(String field,JsonObject json){
String data=null;
if(json.has(field)){
data=json.get(field).getAsString();
}
return data;
}
you can call this method for each of your field:
String pId = getJSONData("proId",jsonInst);
By this way you can not only escape NullPointerException, but also avoid code repetition.

Java CLI arguments syntax for object initialization

I'm looking for a tool which will allow me use command-line-style (preferably POSIX) strings to initialize an object' properties and attributes.
For example, you'd provide it with String input formatted like so:
String input = "--firstName=John --MiddleName=\"Louis Victor\" --lastName=Smith";
... and it would setFirstName("John"), setMiddleName("Louis Victor") and setLastName("Smith") on a given object. (which could be a JavaBean)
Please note that the input is a single String, not an array String[] as is the case with many popular CLI argument "parsers".
This is all similar to args4j but I couldn't get that to work... and I'm hoping to avoid using #annotations.
Does anyone have code/libraries/tools which could accomplish this?
For your use case, forget regular CLI parsers, you need a custom-tailored solution. If you really have such a simple argument syntax (parameters always begin with --, no occurrences of -- in the parameter values), you can use a simple Guava-based solution like this class:
Parse the String Arguments
public class ArgParser{
// split on (optional whitespace) + "--"
private final Splitter paramSplitter = Splitter.on(
Pattern.compile("\\s*\\-{2}")).omitEmptyStrings();
// find key=value (with optional double quotes around value)
private final Pattern keyValuePattern = Pattern
.compile("(.+?)=\"?(.*?)\"?$");
public Map<String, String> getParamValues(final String posixString){
final Map<String, String> paramValues = Maps.newLinkedHashMap();
Matcher matcher;
for(final String param : paramSplitter.split(posixString)){
matcher = keyValuePattern.matcher(param);
if(!matcher.find()){
throw new IllegalArgumentException("Bad parameter: " + param);
}
paramValues.put(matcher.group(1), matcher.group(2));
}
return paramValues;
}
}
Usage
final String input =
"--firstName=John --middleName=\"Louis Victor\" --lastName=Smith";
System.out.println(new ArgParser().getParamValues(input));
Output
{firstName=John, middleName=Louis Victor, lastName=Smith}
Now you can take the map and use it with a Bean library like commons-beanutils (I prefer the Spring BeanWrapper personally, but that only makes sense if you use Spring anyway)
Define the Bean Class
Any way, I'll use this value holder class:
public class Name{
private String firstName;
private String middleName;
private String lastName;
#Override
public String toString(){
return Objects
.toStringHelper(this)
.add("first name", firstName)
.add("middle name", middleName)
.add("last name", lastName)
.toString();
}
// + getters & setters
}
Set the Bean Properties
Now we'll use BeanUtils.populate(Object, Map) to apply the parameter values, like this:
final String input =
"--firstName=John --middleName=\"Louis Victor\" --lastName=Smith";
final Map<String, String> paramValues =
new ArgParser().getParamValues(input);
final Name name = new Name();
BeanUtils.populate(name, paramValues);
System.out.println(name);
Output:
Name{first name=John, middle name=Louis Victor, last name=Smith}
Caveat: Supported Property Types
BeanUtils.populate() supports setting the following property types:
... String, boolean, int, long, float, and double.
In addition, array setters for these
types (or the corresponding primitive
types) can also be identified.
Source: BeanUtilsBean.populate(Object, Map)
If you need parameter conversion beyond that, you should probably look into using the Spring BeanWrapper after all, it's extremely powerful, has many built-in property editors and you can add custom property editors. Just change the code like this:
final Name name = new Name();
final BeanWrapper wrapper = new BeanWrapperImpl(name);
wrapper.setPropertyValues(paramValues);
Reference:
BeanWrapper
PropertyAccessor.setPropertyValues(Map)
If I understand correctly, you are looking for a Java library to parse POSIX-style command line parameters. I used JSAP some time ago and it was really cool (it was using XML configuration back then).
This
-firstName John -lastName Smith
is no POSIX, you mean
--firstName John --lastName Smith
This may be the reason, why you can't get it working.
Update:
As I look at the example, it doesn't look like it could be the reason.

Categories

Resources