I'm trying to migrate an old project to Retrofit library and this project has quite tricky API. So I have a query template like this:
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch();
And I have to add some parameters here of following template:
filter[attributeId]=attributeValueId
For example:
products/search?filter[1]=10&filter[1]=11&filter[2]=20&filter[2]=21
That's how API works and I can't change it. I know that we can pass a list as a parameter, like this:
#Query("filter") List<Integer> attributeValueIds
But how can I also set parameter's name dynamically?
You can use an arrayList! Something like the code below.
#GET(value = "products/search")
Single<ProductSearchResponse> productSearch(
#Query("status") List<Integer> status
);
ArrayList<Integer> queryStatus = new ArrayList<>();
queryStatus.add(0);
queryStatus.add(1);
queryStatus.add(2);
productService.productSearch(queryStatus);
Your url will be like that -> {url}?status=0&status=1&status=2
Thanks to the link, posted by #ILLIA DEREVIANKO (https://github.com/square/retrofit/issues/1324), I've managed to solve the problem with this class:
public class ProxyRetrofitQueryMap extends HashMap<String, Object> {
public ProxyRetrofitQueryMap(Map<String, Object> m) {
super(m);
}
#Override
public Set<Entry<String, Object>> entrySet() {
Set<Entry<String, Object>> originSet = super.entrySet();
Set<Entry<String, Object>> newSet = new HashSet<>();
for (Entry<String, Object> entry : originSet) {
String entryKey = entry.getKey();
if (entryKey == null) {
throw new IllegalArgumentException("Query map contained null key.");
}
Object entryValue = entry.getValue();
if (entryValue == null) {
throw new IllegalArgumentException(
"Query map contained null value for key '" + entryKey + "'.");
}
else if(entryValue instanceof List) {
for(Object arrayValue:(List)entryValue) {
if (arrayValue != null) { // Skip null values
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, arrayValue);
newSet.add(newEntry);
}
}
}
else {
Entry<String, Object> newEntry = new AbstractMap.SimpleEntry<>(entryKey, entryValue);
newSet.add(newEntry);
}
}
return newSet;
}
}
With this we can just use a map, where key is a unique parameter name and value is a List of Strings, that are values for this parameter. Something like this:
ProxyRetrofitQueryMap map = new ProxyRetrofitQueryMap();
List<String> values1 = new ArrayList<>();
values1.add("10");
values1.add("11");
map.put("filter[1]", values1);
List<String> values2 = new ArrayList<>();
values1.add("20");
values1.add("21");
map.put("filter[2]", values2);
You can use #QueryMap annotation like this:
public interface NewsService() {
#GET("/news")
Call<List<News>> getNews(
#QueryMap Map<String, String> options
);
}
Map<String, String> data = new HashMap<>();
data.put("author", "Marcus");
data.put("page", String.valueOf(2));
...
newsService.getNews(data);
More details: https://futurestud.io/tutorials/retrofit-2-add-multiple-query-parameter-with-querymap
Related
public Collection<OwnerDetail> getAllOwners() {
final MorphiaCursor<Listing> listings = datastore.find(Listing.class)
.iterator(new FindOptions()
.projection().include("ownerDetail"));
Map<String, OwnerDetail> map = new HashMap<>();
while (listings.hasNext()) {
final Listing next = listings.next();
if (next.getOwnerDetail() != null) {
map.put(next.getOwnerDetail().getEmail(), next.getOwnerDetail());
}
}
return map.values();
}
I want to remove java code that distinct values by email and handle it by mongodb morphia. How can I do that?
how to merge the list of values to the same Key in hashmap?
if I use the above logic I'm getting below result as an output
{Adam=[[Subject, ComputerScience], [Subject, ComputerScience]]}
But I have to merge like the below result, is it possible to append the list of values to the same key?
{Adam=[Subject, ComputerScience,Subject, ComputerScience]}
public class DemoMap {
public static void main(String[] args) {
HashMap<String, ArrayList<String>> tmeMap = new HashMap<>();
HashMap<String, ArrayList<Object>> mngrMap = new HashMap<>();
ArrayList<Object> emailcontent = new ArrayList<>();
ArrayList<String> mngrList1 = new ArrayList<>();
mngrList1.add("Jay");
mngrList1.add("Aaron");
tmeMap.put("Adam", mngrList1);
//Adam is Senior Manager who has the list of managers under him
emailcontent.add("Subject");
emailcontent.add("ComputerScience");
mngrMap.put("Jay", emailcontent);
mngrMap.put("Aaron", emailcontent);
//Each manager will have the email content
ArrayList<Object> collectionOfManagerContent = new ArrayList<>();
for (Map.Entry<String,ArrayList<Object>> emailEntry : mngrMap.entrySet()) {
collectionOfManagerContent.add(emailEntry.getValue());
}
//our Target is to show the manager's content to Senior Project manager
HashMap<String, ArrayList<Object>> tmeEmailMap1 = new HashMap<>();
for (Map.Entry<String,ArrayList<String>> emailEntry : tmeMap.entrySet()) {
emailEntry.getValue();
tmeEmailMap1.put(emailEntry.getKey(), collectionOfManagerContent);
}
System.out.println(tmeEmailMap1.toString());
}
}
Use addAll() to add all elements of ArrayList into another ArrayList
for (Map.Entry<String,ArrayList<Object>> emailEntry : mngrMap.entrySet()) {
collectionOfManagerContent.addAll(emailEntry.getValue());
}
code below return me list of two objects like this:
[
{
value: "ssss",
},
{
value: "ssss",
},
]
but i want to return list like this:
{
value1:"xxxx",
value2:"xxxx"
}
here is my code
#Override
public List<OrderModel> getOrderByCode(UserEntity user) throws ErrorException {
List<UserEntity> userOrder = userRepository.findByUserAndOrderCodeIn(user, Arrays.asList(OrderCodes.OK, OrderCodes.DONE));
List<OrderModel> om = new ArrayList<OrderModel>();
for(UserAnswerEntity userAnswerEntity : userAnswers){
OrderModel orderModel = new OrderModel();
orderModel.setValue(userAnswerEntity.getValue());
om.add(orderModel );
}
return om;
}
public class OrderModel{
String value;
//get,set
}
can someon tell me how can i return only list like above?
You are trying to make a custom response. One of the possible way is this
Map<String,String> map = new HashMap<String,String>();
map.put("key1", "value1");
map.put("key2", "value2");
System.out.println(map.toString().replace("{", "[").replace("}", "]"));
Change the return type of getOrderByCode() to string and convert your List object to JSON string.
private static final ObjectMapper jsonMapper = new ObjectMapper().setSerializationInclusion(Include.NON_NULL);
return jsonMapper.writeValueAsString(om);
for you example, you can use Map instead of List
try this:
AtomicInteger index = new AtomicInteger()
Function<UserAnswerEntity, String> createIndex = (userAnswer) -> "value" + index.getAndIncrement();
return userAnswers.stream().collect(Collectors.toMap(createIndex, UserAnswerEntity::getValue));
I wrote this code but i am not getting the right output.
System.out.println(map.get(explain)); basically, my final output will be the value of the explain key.
this is my code
package test;
import java.util.Map;
import java.util.Set;
public class Test {
public static void main(String[] args) {
String s = new String(
"http://fts-master.intermesh.net:8020/solr/im-search/select?mc1=%2285665%22&mc3=%2285665A%22&mc4=%2285665B%22&mc5=%2285665LS%22&mc6=%2285665SS%22&mc7=%2285665P%22&mcHigh=%22825%2096447%22&mcHighA=%22825A%2096447A%22&mcHighB=%22825B%2096447B%22&q=shopping%20bags&qt=im.search&ps=2&rows=500&start=0&lat=0&lon=0&spellcheck=true&fq=CustTypeWt:(149%20179%20199%20699%201199%201299%201399%201499)%20AND%20isphoto:true&fq=mcatid:(1224%20825%2085665%2096468%203078%2073252%2096447%205502%20185408%2085676%2096463%20191641%2096472%20139933%20186677%2094993%2099531%2065430%20106446%20129653%2096488%2096478%205575)%20titlex:(%22imswshopbagimsw%22)&fq=-glusrid:(398689)&fq=attribs:(locprefglobal%20locprefnational%20locprefcity%20locprefunknown)&ql1=%22shopbagimsw%22&boost=map(query(%7B!dismax%20qf=mcatid%20v=$mc3%20pf=%22%22%7D),0,0,map(query(%7B!dismax%20qf=mcatid%20v=$mc4%20pf=%22%22%7D),0,0,map(query(%7B!dismax%20qf=mcatid%20q.op=OR%20v=$mcHighA%20pf=%22%22%7D),0,0,map(query(%7B!dismax%20qf=mcatid%20q.op=OR%20v=$mcHighB%20pf=%22%22%7D),0,0,map(query(%7B!dismax%20qf=mcatid%20v=$mc1%20pf=%22%22%7D),0,0,1,1.31%20),6.0),8.0),13.0),19.0)&boost=map(query(%7B!dismax%20qf=mcatid%20v=$mc7%20pf=%22%22%7D),0,0,1,1.2)&boost=map(query(%7B!dismax%20qf=mcatid%20v=$mc5%20pf=%22%22%7D),0,0,map(query(%7B!dismax%20qf=mcatid%20v=$mc6%20pf=%22%22%7D),0,0,1,1.2),1.2)&boost=map(query(%7B!dismax%20qf=titlex%20v=$ql1%20pf=%22%22%7D),0,0,1,1.22)&boost=productqualityscore&debugQuery=true&fq=displayid:15004840733");
Map<String, Object> map = Utility.getResults(s);
System.out.println(map);
Set<String> keys = map.keySet();
for (String response : keys) {
System.out.println(map.get(response));
{
for (String debug : keys) {
System.out.println(map.get(debug));
{
for (String explain : keys) {
System.out.println(map.get(explain));
}
}
}
}
}
}
}
The problem seems to be in your below code. This code is not making much sense. Basically, this code is iterating over same set. Ex: if your "map" is {(1,a),(2,b)} and "keys" is {1,2}, your output will be aaabbb. Are you sure you want to do this?
for (String response : keys) {
System.out.println(map.get(response));
{
for (String debug : keys) {
System.out.println(map.get(debug));
{
for (String explain : keys) {
System.out.println(map.get(explain));
}
}
}
}
}
instead, you might want to do something like:
for (String response : keys) {
String res = map.get(response);
String debug = map.get(res)
... //any other operation you want to link with response object.
}
Or something like
for (String response : keys) {
String res = map.get(response);
Response resObj = new Response(res);
Debug deb = resObj.getDebug(); //assuming debug is field in respose body.
... //any other operation you want to link with response object.
}
I think you are trying to do something like this in place of the nested for-loops -
Map<String, Object> map = new HashMap<String, Object>();
Map<String, Object> debugMap = (Map<String, Object>) map.get("debug");
Map<String, Object> explainMap = (Map<String, Object>) map.get("explain");
Stream.of(explainMap.keySet().toString()).forEach(System.out::println);
i am trying to render a key,value Map to a template and then show there in this way:
#(twittsIfollow: Map[String, String])
.....
#if(twittsIfollow != null) {
#for((key, value) <- twittsIfollow) {
#key
#value
}
}
it says, it is wrong. is there a scala tag for Map keys values?
here is my method:
public static Map<String, String> alltwitts(List<Long> otherIDs) {
Map<String, String> results=new HashMap<String, String>();
for (Long id: otherIDs) {
Query selected_twitt = JPA.em().createQuery("select u.twitt from Twitt u where " + " u.whose = ?").setParameter(1, id);
String twOwner = User.getOneUser(id);
String twitt = (String) selected_twitt.getSingleResult();
results.put(twOwner, twitt);
}
return results;
}
then i render to template in this place:
Map<String, String> twittsIfollow = Twitt.alltwitts(IDusersIamFollowing);
return ok(microblog.render(twittsIfollow));
now it is saying: [NonUniqueResultException: result returns more than one elements]
thanks
Simply
#for((key, value) <- twittsIfollow) {
#key
#value
}
BTW, if you are using Scala, twittsIfollow should never be null. Prefer using Option.
how i solved:
public static Map<String, List<String>> alltwitts(List<Long> otherIDs) {
Map<String, List<String>> results=new HashMap<String, List<String>>();
for (Long id: otherIDs) {
Query selected_twitt = JPA.em().createQuery("select twitt from Twitt where " + " whose = ? order by id").setParameter(1, id);
String twOwner = User.getOneUser(id);
List<String> twitt = selected_twitt.getResultList();
results.put(twOwner, twitt);
}
System.out.println(results);
return results;
}
then in my Application:
Map<String, List<String>> twittsIfollow = Twitt.alltwitts(IDusersIamFollowing);
return ok(microblog.render(twittsIfollow));
then in my template:
#(twittsIfollow: Map[String, List[String]])
and
#if(twittsIfollow != null) {
#for((key, value) <- twittsIfollow) {
#for(innervalue <- value){
Username: #key
Twitt: #innervalue
}
}
}
just for those who are dumb like me :D and looking for solution like this..
thanks for help,guys..
#doniyor, I'm surpriesed as I showed you the way in other question not so long ago.
By the way I think it will be better to build, pass and iterate twittsIfollow as a List of Maps
then you can use
#if(twittsIfollow != null) {
#for(twitts <- twittsIfollow) {
the value is: #twitts.get("key")
}
}