Java QueryParam with key and value in the same parameter - java

I'm creating a endpoint (using Jersey annotations) that receives a list of Strings as it's parameter. The strings need to contain a key and a value.
So on the url it would look something like
?params=key1=value1&params=key2=value2&params....
Two questions:
I'm not sure if the above example would work, I assume you would have to encode the = sign between key and value. Is that correct?
Is there a better or more standard way to approach this?
Obviously the most standard way would be to have the RHS be the key and the LHS of the equal sign would be the value. The problem is I don't want to define every possible key value pair in my method signature. I want to accept a general list of keys and values and let the user pass in the pairs that are relevant to their query.
So far I've tried several google queries but haven't found an answer:
java url key and value parameter
java url parameters with key and value
list of key value pairs in url java
Storing a list of key value pairs in a url parameter, javascript. (has an answer for php but I'm using Java, would this work in Java?)
how to send an array in url request (suggests the above would work in java, if so, can the index be a string like &params[key2]=value2...?)

Yes. Jersey can handle it even = between key and value is not encoded.If query parameter is params=key1=value1&params=key2=value2 , the params list below will be [key1=value1, key2=value2]
#GET
public Response q34211549(#QueryParam("params") List<String> params) {
//parse params list and convert it into key and value
}
You can also consider to create a ParamConverter to let Jersey to do this conversion for you.
Reference
JAX-RS ParamConverter and ParamConverterProvider Example

Related

Retrofit query with hashmap parameters of comma separated list java

I am trying to use the Kasses Spotify web api to get a series of recommended songs for the user. In the get request the there are two arguments a map and a call back. For the callback all good. But for the map I am not sure how to format the parameters.
This is the documentation:
#GET(value="/recommendations")
void getRecommendations(#QueryMap
Map<String,Object> options,
retrofit.Callback<Recommendations> callback)
Create a playlist-style listening experience based on seed artists, tracks and genres.
Parameters:
options - Optional parameters. For list of available parameters see endpoint documentation
callback - callback method
it says the parameters (options) are in the format Map and it points to the endpoint documentation for the parameters here:
https://developer.spotify.com/web-api/get-recommendations/
So I can see that some are optional and some are required. One example of a required one is here:
Argument:
seed_genres
Value:
A comma separated list of any genres in the set of available genre seeds.
So I am for my map in the form of:
Map <String, Object>
I am guessing String would be "seed_genres"
But for the object I am not sure how to format that:
For example if I was looking at reggae, jazz, metal.
How do I make that a comma separated list even if it is a String object I am still not sure how to format that.
Thanks in advance for your help

Android HttpUrlConnection send multiple parameters with same key

How can i add multiple values with the same name in a HttpUrlConnection request.
example:
HashMap<String, String> params = new HashMap<>();
params.put("key[]", value1)
params.put("key[]", value2)
If i try to add multiple values with the same in postman i works fine, the application will send only one values (depends on request property, URLConnection setRequestProperty vs addRequestProperty).
I want to add both values as a parameter with the same name
This is not possible with Maps or HashMaps.
Taken from Oracles documentation on Maps:
http://docs.oracle.com/javase/7/docs/api/java/util/Map.html
An object that maps keys to values. A map cannot contain duplicate keys; each key can map to at most one value.
The put command will replace the previous value associated with the given key in the map (you can think of this like an array indexing operation for primitive types).
The Oracle Documentation for put states:
Associates the specified value with the specified key in this map. If
the map previously contained a mapping for the key, the old value is
replaced.
Returns the previous value associated with key, or null if there was
no mapping for key.
This can be found here:
http://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html#put%28K,%20V%29
Alternatively You can do this and it will work fine.
You can make a JSONArray like this
JSONArray array = new JSONArray();
array.put("value1");
array.put("value2");
//and then you can send them as parameter like this-
params.put("key", array.toString());
It is not possible with params.put() But it is possible with params.add()
Reference : Difference between RequestParams add() and put() in AndroidAsyncHttp

rest-assured jsonPath returns HashMap instead of LinkedHashMap

This pertains to Java.
I would like to be able to change the default behavior of how a JsonPath object returns itself when parsed from a json response so that I can still leverage the methods it comes with such as getMap(), getList(), etc. Ideally I would like all the JsonPath methods to return their Map objects as a LinkedHashMap instead of a HashMap or at the minimum have the getMap() method return as a LinkedHashMap so I can preserve key ordering.
The below response object's json key ordering matches the browser's json response:
Response response = given().get(urlQuery).then().extract().response();
However, when you attempt to grab an object or value from the response via jsonPath() then the json key ordering is all screwed up due to the fact that JsonPath methods are leveraging a HashMap instead of a LinkedHashMap behind the scenes such as the code snippet below does:
Map map = response.jsonPath().getMap("path.to.a.map");
I'm hoping the answer lies within changing the config to something, or overloading a method somewhere, etc. as I like using the rest-assured library for all my json parsing except I now need to preserve key ordering.
Aside from the response object as mentioned above, I would be content if I could at the minimum get the JsonPath methods to return the json in the correct order as shown by the below code example:
import com.jayway.restassured.path.json.JsonPath;
String json = "{\"fields\":{\"field1\":1,\"field2\":2,\"field3\":3,\"field4\":\"4\"}}";
// The value of the JsonPath object stays in the correct order: {"fields":{"field1":1,"field2":2,"field3":3,"field4":"4"}}
JsonPath jsonpath = new JsonPath(json);
// When using any of the JsonPath methods the order is messed up and returns: "{field4=4, field3=3, field2=2, field1=1}"
Object map = jsonpath.getMap("fields");
I would like to somehow get the JsonPath methods to keep the order by leveraging LinkedHashMap types but am unsure how or where to implement this.

Can I use varargs in a retrofit method declaration?

I've got an API endpoint that is defined as:
GET https://api-server.com/something/{id_or_ids}
where ids can be a single object id or a comma separated list of ids.
e.g.
https://api-server.com/something/abcd1234
https://api-server.com/something/abcd1234,abcd4567,gdht64332
if a single id is given (and a matching object is found) I get back a json object:
{ "blah" : "blah" }
If multiple ids are given, I get the response in a json array:
[{"blah1":"bleh"}, {"blah2":"meh"}, {"blah3":"blah"}]
I'm currently thinking that I should implement this as two methods (can it be done in one?):
one that takes a single id and returns a single object:
#GET("/something/{id}")
void getObject (#Path("id") String objectId, Callback<MyObject> callback)
and
one that takes multiple ids and returns an array of objects.
#GET("/something/{ids}")
void getObject (Callback<MyObject[]> callback,#Path("ids") String ... objectIds)
Is there a way to feed the 2nd method varargs and concatenate them in the id field?
Thanks
Retrofit can't know how you want to join the strings in the path. While commas seem obvious, there's no reason why someone might want pipes (|) or colons (:) or whatever.
Because of this fact, we don't do anything and rely on you to choose.
There's two solutions to this:
Use String as the argument type and join at the call site. For example:
foo.getObject(Joiner.on(',').join(things));
Use a custom object whose toString() method deals with returning the correct format for one or many objects.

Does this return the pointer to the values or does it copy the values?

Well OK, I got confused. I believe it returns the pointer to the original map?
private HttpServletRequest originalRequest;
Map params = originalRequest.getParameterMap();
params.remove("parameter-to-remove");
params.put("parameter-to-add", "<a value>");
Now are the parameters in the originalRequest going to change after these actions? Or does it just copy the values to params and it doesn't matter what I do with them and nothings going to be changed in originalRequest?
Returned map is immutable Map, that could be the reason why you are not seeing the changes reflected.
As per getParameterMap javadoc
an immutable java.util.Map containing parameter names as keys and parameter values as map values. The keys in the parameter map are of type String. The values in the parameter map are of type String array.
If you would like to set some value to request, you should use setAttribute.
No, you are not allowed to remove or add any request parameter(s) to the request object. They must remain (as they arrived to the server) until the request object goes out of scope (after the end of the request processing cycle).
Logically, if you were allowed to do something like that, then the request object would not represent the original request any more. During the whole request processing cycle, we want to process the request sent by the client, not the one that has been tampered.
The method you should use instead is void setAttribute(java.lang.String name, java.lang.Object o).

Categories

Resources