begin array but was string GSON - rest

I have a Web Service REST :
#Path("/Vehicles")
public class Vehicles{
#GET
#Path("/Cars")
#Produces(aplicattion/json)
public String Cars() {
Car[] cars = Consulting my database...
Gson gson = new Gson();
return gson.toJson(cars);
}
I consume the web service:
try {
HttpClient httpClient = new DefaultHttpClient();
HttpGet get = new HttpGet(
"http://localhost:8080/Concessionaire/rest/Vehicles/Cars");
HttpResponse resp = httpClient.execute(get);
String respGET = EntityUtils.toString(resp.getEntity());
Gson gson = new Gson();
Cars[] c = gson.fromJson(respGET,Cars[].class);
}catch(Exception e){
}
But appears this exception: Expected BEGIN_ARRAY but was String at line 1 colum 6
What is the problem ?

Your method returns a String
public String Cars()
The client code expects a Car array
Cars[] c = gson.fromJson(respGET,Cars[].class);
Gson expects the BEGIN_ARRAY event while parsing the json but instead finds a String. To fix it, send a Cars[] using the jersey Response class and change the return type to Response.
return Response.ok(myCarsArray).build();

Related

Spring REST Endpoint Returning String instead of JSON

The following endpoint returns a username as a string.
How would I structure it to return a json object that contains a key with that string as its value (e.g., {"user":"joeuser"}?
#GetMapping(value = "/getUser", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> getUser() {
HttpHeaders responseHeaders = new HttpHeaders();
CustomUserAuthentication authentication = (CustomUserAuthentication) SecurityContextHolder.getContext().getAuthentication();
return ResponseEntity.ok().headers(responseHeaders).body(String.valueOf(authentication.getPrincipal()));
}
Using some Json library (like gson), build the Json object and return it in the body instead of the String. Make sure response content-type is application/json
You can also manually build the String that looks like Json but content to must be as above.
Spring can do what you want, but you need to return something that Spring needs to marshal into JSON. From my previous answer: https://stackoverflow.com/a/30563674/48229
#RequestMapping(value = "/json", method = RequestMethod.GET, produces = "application/json")
#ResponseBody
public Map<String, Object> bar() {
HashMap<String, Object> map = new HashMap<String, Object>();
map.put("test", "jsonRestExample");
return map;
}

How to parse various answers from server and Retrofit

The server can answer like:
{ "data1":"value", "data2":"value" }
or:
{ "error":"text" }
or:
{ "json":"{ "error":"text" }" }
How to parse various answers from the server using retrofit.
Maybe I should make a rich POJO like:
class MyAnswer {
String data1;
String data2;
String error;
// etc
}
I recommend you to use Google's Gson library to Serialize/Deserialize Json strings to POJO's and deserialize back.
Retrofit2 also supports Gson as a converter.
Add compile 'com.squareup.retrofit2:converter-gson' to your build.gradle and create Retrofit instance like below:
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(client)
.addConverterFactory(GsonConverterFactory.create())
.build();
Define your Java classes and annotate them with Gson's SerializedName tag.
public class MyAnswer {
#SerializedName("data1")
public String data1;
#SerializedName("data2")
public String data2;
#SerializedName("error")
public String error;
}
Then you can get your POJO on the onResponse method:
#Override
public void onResponse(Call<ExampleClass> call, Response<ExampleClass> response) {
ExampleClass exampleClass = response.body();
......
}
You can also deserialize yourself from Json:
Gson gson = new GsonBuilder().create();
ExampleClass ec = gson.fromJson(jsonString, ExampleClass.class);
Or serialize to Json:
ExampleClass ec = new ExampleClass();
ec.data1 = "Some text";
ec.data2 = "Another text";
Gson gson = new GsonBuilder().create();
String jsonString = gson.toJson(ec);
You can also create nested/complex structures with Gson.
For more information, visit their user guide.

Apache HttpClient - REST API: Issue in converting response to customized object which is put as SerializableEntity

I am using Apache HttpClient to put/get customized object using REST APIs. Below is the sample code. My putObject() method works fine and I could serialize Person object and put properly. However, while getting the object, I got below error:
Exception in thread "main" java.lang.ClassCastException: [B cannot be cast to Person at MyTest.demoGetRESTAPI(MyTest.java:88) at MyTest.main(MyTest.java:21)
Seems the code to build Person object out of response entity is not correct
HttpEntity httpEntity = response.getEntity();
byte[] resultByteArray = EntityUtils.toByteArray(httpEntity);
Person person = (Person)SerializationUtils.deserialize(resultByteArray);
Am I doing somthing wrong while getting byte[] array and converting to Person object. Please help me out to solve this issue.
Complete Example Program:
import java.io.Serializable;
import org.apache.commons.lang.SerializationUtils;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.HttpClient;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.entity.SerializableEntity;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;
public class MyTest {
public static void main(String[] args) throws Exception {
putObject();
getObject();
}
public static void putObject() throws Exception
{
HttpClient httpClient = new DefaultHttpClient();
Person person = new Person();
person.setName("Narendra");
person.setId("1");
try
{
//Define a postRequest request
HttpPut putRequest = new HttpPut("http://localhost:9084/ehcache-server/rest/screeningInstance/2221");
//Set the API media type in http content-type header
putRequest.addHeader("content-type", "application/x-java-serialized-object");
//Set the request put body
SerializableEntity personSEntity = new SerializableEntity(SerializationUtils.serialize(person));
putRequest.setEntity(personSEntity);
//Send the request; It will immediately return the response in HttpResponse object if any
HttpResponse response = httpClient.execute(putRequest);
//verify the valid error code first
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 201)
{
throw new RuntimeException("Failed with HTTP error code : " + statusCode);
}
}
finally
{
//Important: Close the connect
httpClient.getConnectionManager().shutdown();
}
}
public static void getObject() throws Exception
{
DefaultHttpClient httpClient = new DefaultHttpClient();
try
{
//Define a HttpGet request; You can choose between HttpPost, HttpDelete or HttpPut also.
//Choice depends on type of method you will be invoking.
HttpGet getRequest = new HttpGet("http://localhost:9084/ehcache-server/rest/screeningInstance/2221");
//Set the API media type in http accept header
getRequest.addHeader("accept", "application/x-java-serialized-object");
//Send the request; It will immediately return the response in HttpResponse object
HttpResponse response = httpClient.execute(getRequest);
//verify the valid error code first
int statusCode = response.getStatusLine().getStatusCode();
if (statusCode != 200)
{
throw new RuntimeException("Failed with HTTP error code : " + statusCode);
}
//Now pull back the response object
HttpEntity httpEntity = response.getEntity();
byte[] resultByteArray = EntityUtils.toByteArray(httpEntity);
Person person = (Person)SerializationUtils.deserialize(resultByteArray);
}
finally
{
//Important: Close the connect
httpClient.getConnectionManager().shutdown();
}
}
}
class Person implements Serializable{
String name;
String id;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
#Override
public String toString() {
return "Person [name=" + name + ", id=" + id + "]";
}
}
I got the solution. It was mistake in my code:
While putting object, I have written below code. That was doing two time serialization. First from Person object to byte[] and second from byte[] to byte[].
SerializableEntity personSEntity = new SerializableEntity(SerializationUtils.serialize(person));
putRequest.setEntity(personSEntity);
This is the right approach:
SerializableEntity personSEntity = new SerializableEntity(person);
putRequest.setEntity(personSEntity);
After getting binary from REST, code should be like below to get Object:
HttpEntity httpEntity = response.getEntity();
InputStream inputStream = null;
try {
inputStream = httpEntity.getContent();
Person p = (Person) SerializationUtils.deserialize(inputStream);
System.out.println("Person:" + p.getName());
}
finally {
inputStream.close();
}
This worked like CHARM !!

Jersey client. MultivaluedMap goes empty

My RESTful client has this method:
public void testGetCateogrywiseData() {
ClientConfig config = new DefaultClientConfig();
Client client = Client.create(config);
client.addFilter(new LoggingFilter(System.out));
WebResource service = client
.resource("http://localhost:8080/MyApp/rest/publicdata");
#SuppressWarnings("rawtypes")
MultivaluedMap queryParams = new MultivaluedMapImpl();
queryParams.add("latitude", "18.522387");
queryParams.add("longitude", "73.878437");
queryParams.add("categoryID", "2");
service.queryParams(queryParams);
ClientResponse response = service.get(ClientResponse.class);
System.out.println(response.getStatus());
System.out.println("Form response " + response.getEntity(String.class));
}
On the server side the method looks like this:
#Path("publicdata")
#GET
#Produces(MediaType.TEXT_HTML)
#Consumes(MediaType.APPLICATION_FORM_URLENCODED)
public String getPublicData() throws JSONException {
MultivaluedMap<String, String> valueMap = uriInfo.getQueryParameters();
Long latString = Long.parseLong(valueMap.getFirst("latitude"));
Long lonString = Long.parseLong(valueMap.getFirst("longitude"));
Long categoryId = Long.parseLong(valueMap.getFirst("categoryID"));
// Do necessary stuff and return json string
return null;
}
My problem is the valueMap at the server end is always empty. It never gets the three parameters that I have sent from the client code. What am I missing?
The problem happens on this line:
service.queryParams(queryParams);
It successfully adds the query params, but it does not change the original service, it returns a new one to you. To make it work you need to change to this:
service = service.queryParams(queryParams);

Spring 4 Restfull Service with bean

I am trying to create a simple Server / Client application that can send a bean as parameter instead of String but failing below is my code
Server
#Controller
public class GreetingController {
private static final String template = "Hello, %s!";
private final AtomicLong counter = new AtomicLong();
#RequestMapping(method=RequestMethod.POST,value="/returnGreet")
public #ResponseBody Greeting returnGreet(
#RequestBody(required=false) Greeting greet) {
if(greet == null)
return new Greeting(counter.incrementAndGet(),
String.format(template, greet));
else
return new Greeting(0,"Testing");
}
}
Client
RestTemplate restTemplate = new RestTemplate();
MultiValueMap<String,Greeting> greet = new LinkedMultiValueMap<String, Greeting>();
greet.add("greet", new Greeting(0,"XOXO"));
greeting = restTemplate.postForObject("http://localhost:8080/returnGreet",greet, Greeting.class,greet);
System.out.println("Content: " + greeting.getContent());
System.out.println("Id: " + greeting.getId() );
The result is always null for the object greet at the server side.
Any Idea ?
You're not using the RestTemplate correctly. Why are you passing a MultiValueMap as the Entity to be sent? This won't get serialized the way your Server expects.
Just use the Greeting object directly.
restTemplate.postForObject("http://localhost:8080/returnGreet", new Greeting(0, "XOXO"), Greeting.class);
Also, the last argument is not necessary, you don't have any URI variables.