I am using resteasy to send key/value pairs in between some restful web-services.
to post a list of these pairs i use this snippet
List<Pair> pairs = new ArrayList<>();
pairs.add(new Pair("name", "Arnold"));
pairs.add(new Pair("age", "20"));
ResteasyClient resteasyClient = getClient();
ResteasyWebTarget target = resteasyClient.target(targetURI);
Invocation.Builder request = target.request();
request.post(Entity.entity(entity, MediaType.APPLICATION_JSON_TYPE));
Pair is just an unannotated Class with
public String key,
public String value
default constructor
(key,value) constructor
The target resource an receive this via:
#POST
#Path("/metadata")
#Consumes(MediaType.APPLICATION_JSON)
public Response postMetadata(List<Pair> properties) {...
the jax-rs resource can read the List correctly.
Now the other way is the Problem:
The Retrieval Resource is defined as:
#GET
#Path("/getUrl.../{id}")
#Produces(MediaType.APPLICATION_JSON)
public Response getMetadata(#PathParam("id") String id) {
data_from_hibernate = em.find(id);
...
List<Pair> properties = new ArrayList<>();
//fill List from data
return Response.ok().entity(properties).build();
Client side is:
Response response = request.get("http://getUrl.../"+id);
List<Pair> properties = response.readEntity(List.class);
logger.info("got properties != null? " +(properties!=null));
logger.info("size: "+properties.size());
logger.info("[0]" + properties.get(0));
logger.info("type: "+properties.get(0).getClass().getName());
The List is not null;
size is correct;
get(0) does output in a strange format: [0]{"name": "value"};
this is followed by the strange format's reason: an Exception tells me that:
java.util.LinkedHashMap cannot be cast to Pair
How is properties a LinkedHashMap at this point, or rather: a List of LinkedHashMaps?
Without type information (when you use readEntity), Jackson (the underlying deserializer) will convert arbitrary JSON objects to LinkedHashMap.
When using readEntity, you provide generic type information by using GenericType.
List<Pair> properties = response.readEntity(new GenericType<List<Pair>>(){});
Related
I have set which contains string ["a" , "b" , "c"] , I want to POST json data like (comma seperated and one string)
Here is
JSON
{"view" : "a,b,c",
"fruits" : "apple"}
to the endpoing using Resttemplate postForObject method? I have used GSON but that is not working in my project. Are there any other alternatives?
Here is my code
private run(set<data> datas) {
Set<string> stack = new hashset<>();
iterator<data> itr = datas.iterator();
while (itr.hasnext()) {
data macro = itr.next();
if (//some condition) {
stack.add(macro);
}
}
}
}
Resttemplate.getmessageconverters().add(stringconvertor);
String result = resttemplate.postforobject(endpoint, request, String.class);
}
If the data is in a specific class like format, you could go with the POJO approach that is encouraged by Spring Boot. But looking at your example, it seems like you want to achieve a one time JSON Object response.
import org.json.simple.JSONObject;
public static void run(set<data> datas, string endpoint){
// build your 'stack' set
String joined = String.join(",", stack);
JSONObject obj=new JSONObject();
obj.put("view",joined);
obj.put("fruits","apple");
//return the jsonObject as the response to your entrypoint using your method
}
You could also try the following if you use #ResponseBody annotation in Spring Boot that will convert the Response Body to the appropriate (JSON) format.
HashMap<String, String> map = new HashMap<>();
map.put("view", joined);
map.put("fruits", "apple");
return map;
This is my 1st project in java spring. So i m trying to figure out the best way to do things.
I have several Rest Apis in my project for which different kinds of API response will be sent.
Somewhere i m getting data in List Format, somewhere else another format. So i m trying to figure out the best way to send response in JSON format.
One of the API Response i have is this:
{
"result": "true",
"message": null,
"data": "{\"id\":1,\"firstName\":\"test\",\"lastName\":\"test\",\"emailId\":\"test#test.com\",\"mobileNo\":\"1234567890\",\"alternateMobileNo\":\"1234567890\",\"username\":\"test\",\"password\":\"7c4a8d09ca3762af61e59520943dc26494f8941b\",\"status\":\"active\",\"userRole\":\"test\",\"dateCreated\":\"Feb 6, 2019\",\"permissions\":\"\"}"
}
My biggest issue is the formatting of data key in the above JSON.
This is my controller action:
#RequestMapping(value = "/admin/staff/get", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public Map get(HttpServletRequest request, #RequestParam Map<String, String> parameters) {
Map<String, String> response = new HashMap<>();
Gson gson = new Gson();
Staff staff = new Staff();
staff.setId(new Integer(parameters.get("id")));
List validateToken = loginAuthTokenService.validateToken(new Integer(request.getHeader("loginId")), request.getHeader("loginType"), request.getHeader("token"));
if (validateToken.size() > 0) {
Staff staffDetails = staffService.getStaff(staff.getId());
response.put("result", "true");
response.put("data", gson.toJson(staffDetails));
} else {
response.put("result", "false");
response.put("message", "No records found.");
}
return response;
}
Should I create a separate Class for sending API Response or anyone please guide me the proper way of sending response.
Thanks
Gson#toJson(Object) returns a String and that String is mapped as JSON key in your map.
You don't have to convert your object to a JSON, Spring will do it for you (it uses Jackson as JSON mapper so you don't have add Gson dependency to your project.
A simple and working implementation could be something like:
#RequestMapping(value = "/admin/staff/get", method = RequestMethod.POST, consumes = MediaType.APPLICATION_FORM_URLENCODED_VALUE)
public ResponseEntity<?> get(
#RequestParam("id") Integer id,
#RequestHeader("loginId") Integer loginId,
#RequestHeader("loginType") String loginType,
#RequestHeader("token") String token) {
List validateToken = loginAuthTokenService.validateToken(loginId, loginType, token);
if (!validateToken.isEmpty()) {
Stuff stuff = staffService.getStaff(id);
return ResponseEntity.ok(stuff);
}
return ResponseEntity.notFound().body("No records found.");
}
Also consider to not return a generic map from your method, but the Stuff object your front-end needs. In case of failure you should return a failure object with a specific http response code (e.g. 404, 400, 500...).
Take a look at this guide.
To format the the data attribute , you can store it in a map :-
Map<String, Object> map1= new HashMap<String, Object>();
and is you have multiple data attributes you can create an ArrayList of Maps :-
ArrayList<Map<String, Object>> dataClerk = new ArrayList<Map<String,Object>>();
I had a similar usecas so i used the below code :-
obj = parser.parse(response);
JSONObject jobj = (JSONObject)parser.parse(response);
JSONArray jsonarr_1 = (JSONArray) jobj.get(item);
for(int i=0 ;i<jsonarr_1.size();i++) {
Map<String, Object> entry = new HashMap<String, Object>();
org.json.simple.JSONObject temp= (org.json.simple.JSONObject)
jsonarr_1.get(i);
Set<String> attributes= temp.keySet();
for(String s: attributes) {
entry.put(s, temp.get(s));
}
}
I'm going to receive requests with a JSON object passed as querystring which will no longer have a JSON structure, it will be something like this:
http:/mysite/api/doSomething?name=name&address=address...
I need to store it as a String following a JSON structure, the problem is that the original JSON object passed as querystring may have attributes that are collections and I can't figure out a way to parse it back correctly.
Is there a Java function or a library to achieve this easily?
I assume you are using spring mvc/jersey in controller. In that case you can do something like this
#RequestMapping(value = "/mysite/api/doSomething", method = RequestMethod.GET)
public String search(
#RequestParam Map<String,String> allRequestParams) {
JSONObject js = new JSONObject();
for (Map.Entry<String,String> entry : allRequestParams.entrySet()){
js.put(entry.getKey(), entry.getValue());
}
String jsonString = js.toString();
}
Basically get all the queryparam and construct JSONObjcet, JACKSON library will not be of much use here.
It's absolutely strange, but I can't find any Java/Android URL parser that will be compatible to return full list of parameters.
I've found java.net.URL and android.net.Uri but they are can't return parameters collection.
I want to pass url string, e.g.
String url = "http://s3.amazonaws.com/?AWSAccessKeyId=123&Policy=456&Signature=789&key=asdasd&Content-Type=text/plain&acl=public-read&success_action_status=201";
SomeBestUrlParser parser = new SomeBestUrlParser(url);
String[] parameters = parser.getParameterNames();
// should prints array with following elements
// AWSAccessKeyId, Policy, Signature, key, Content-Type, acl, success_action_status
Does anyone know ready solution?
There is way to get collection of all parameter names.
String url = "http://domain.com/page?parameter1=value1¶meter2=value2";
List<NameValuePair> parameters = URLEncodedUtils.parse(new URI(url));
for (NameValuePair p : parameters) {
System.out.println(p.getName());
System.out.println(p.getValue());
}
This static method builds map of parameters from given URL
private Map<String, String> extractParamsFromURL(final String url) throws URISyntaxException {
return new HashMap<String, String>() {{
for(NameValuePair p : URLEncodedUtils.parse(new URI(url), "UTF-8"))
put(p.getName(), p.getValue());
}};
}
usage
extractParamsFromURL(url).get("key")
Have a look at URLEncodedUtils
UrlQuerySanitizer added in API level 1
UrlQuerySanitizer sanitizer = new UrlQuerySanitizer(url_string);
List<UrlQuerySanitizer.ParameterValuePair> list = sanitizer.getParameterList();
for (UrlQuerySanitizer.ParameterValuePair pair : list) {
System.out.println(pair.mParameter);
System.out.println(pair.mValue);
}
The urllib library will parse the query string parameters and allow you to access the params as either a list or a map. Use the list if there might be duplicate keys, otherwise the map is pretty handy.
Given this snippet:
String raw = "http://s3.amazonaws.com/?AWSAccessKeyId=123&Policy=456&Signature=789&key=asdasd&Content-Type=text/plain&acl=public-read&success_action_status=201";
Url url = Url.parse(raw);
System.out.println(url.query().asMap());
for (KeyValue param : url.query().params()) {
System.out.println(param.key() + "=" + param.value());
}
The output is:
{Policy=456, success_action_status=201, Signature=789, AWSAccessKeyId=123, acl=public-read, key=asdasd, Content-Type=text/plain}
AWSAccessKeyId=123
Policy=456
Signature=789
key=asdasd
Content-Type=text/plain
acl=public-read
success_action_status=201
I am trying to pass an array of long with Jersey :
In the client side i have trying something like that :
#GET
#Consume("text/plain")
#Produces("application/xml)
Response getAllAgentsById(#params("listOfId") List<Long> listOfId);
Is there a way to realize something like that?
Thanks in advance!
If you want to stick to "application/xml" format and avoid JSON format, you should wrap this data into a JAXB annotated object, so that Jersey can use the built-in MessageBodyWriter / MessageBodyReader.
#XmlRootElement
#XmlAccessorType(XmlAccessType.FIELD)
public ListOfIds{
private List<Long> ids;
public ListOfIds() {}
public ListOfIds(List<Long> ids) {
this.ids= ids;
}
public List<Long> getIds() {
return ids;
}
}
On the client side (using Jersey client)
// get your list of Long
List<Long> list = computeListOfIds();
// wrap it in your object
ListOfIds idList = new ListOfIds(list);
Builder builder = webResource.path("/agentsIds/").type("application/xml").accept("application/xml");
ClientResponse response = builder.post(ClientResponse.class, idList);
If you just need to pass array of long its possible without any problem. But I will probably pass the long as comma delimited string. (123,233,2344,232) and then split the string and convert in to long.
If not, I suggest you use Json Serialization. If you are using java client, then google gson is a good option. In client side, I will encode my list:
List<Long> test = new ArrayList<Long>();
for (long i = 0; i < 10; i++) {
test.add(i);
}
String s = new Gson().toJson(test);
And pass this string as post param. In the server side, I will decode like this.
Type collectionType = new TypeToken<List<Long>>() {
} // end new
.getType();
List<Long> longList = new Gson().fromJson(longString,
collectionType);