I have a java service which calls an API and gets the following in return
{
"status": {
"service1": {
"available": true,
...
},
"service2": {
"available": false,
...
},
...
}
}
How can i use .readEntity (or something else) to get the object for a given field; say service2
Or just convert all objects inside status to a List<> of objects
String output = response.readEntity(String.class); works, but i dont know how to parse it properly to something useful as i dont want to search in the string
import javax.ws.rs.client.Client;
import javax.ws.rs.core.Response;
Response response = client
.target(url)
.request()
.get();
String output = response.readEntity(String.class);
You can model the data with a POJO and use that to extract the data. A model of the JSON that you've posted might look something like
public static class ResponseData {
private Map<String, Service> status;
// getters and setters
public static class Service {
private boolean available;
// getters and setters
}
}
The getters and setters should use JavaBean naming convention. Then make sure you have a JSON provider such as Jackson
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-json-jackson</artifactId>
<version>${jersey2.version}</version>
</dependency>
Now you can simply pass the POJO class to the readEntity() method and it will deserialize the JSON into your POJO class.
ResponseData resData = res.readEntity(ResponseData.class);
Service service2 = resData.getStatus().get("service2");
For more details on modeling your JSON, you can do a Google search for "data binding with Jackson"
Related
i'm trying to consume a Json response using RestTemplate in java with Jackson annotations, and i have a resource that have many name properties like so:
{
-name1:{
id:2,
price:12,
name:"Bob:
},
-name2:{
id:111,
price:1.1,
name:"Ron:
},
-name3:{
id:10,
price:33,
name:"jhon:
},
}
and the list go on like this.
this is my code of how to get one of the entities, like name1 object:
public class Class1 {
private RestTemplate restTemplate;
private String url = "https://url.com/api";
private Response response;
private Market market ;
public class1(){
restTemplate = new RestTemplate();
response = restTemplate.getForObject(url,Response.class);
}
#Override
public Market getResults() {
market = response.getResult();
System.out.println(Market);
return null;
}
}
and the response class is like so :
#JsonIgnoreProperties(ignoreUnknown = true)
#Getter
#Setter
#NoArgsConstructor
public class Response {
#JsonProperty("name1")
private Market result;
}
how can i get all those elements as an array or ArrayList?
this API is from 3rd party website and there's many entities liek that in the Json response.
thanks in advance.
So in the Json above, it is not an array but a list of key value pair.
This is what an array looks like in Json:
{
marketResults: [
{
id:2,
price:12,
name:"Bob:
},
{
id:111,
price:1.1,
name:"Ron:
},
{
id:10,
price:33,
name:"jhon:
}
]
}
Then what you could have done is:
public class Response {
private List<Market> marketResults;
}
But since your example is a map, you need to to use a MAP
public class Response {
private Map<String, Object > marketResults;
}
That post actually similar to yours: Reading JSON map structure via spring boot
If you can use Gson library that has native support for this use-case.
Keeps your code clean and typed.
#Getter
#Setter
public class Response {
#SerializedName(value = "name1", alternate={"name2","name3"})
private Market result;
}
#SerializedName is the #JsonProperty equivalent in Gson.
I have the following JSON that will be passed as part of a HTTP request, in the message body.
{
"names": [
{
"id":"<number>",
"name":"<string>",
"type":"<string>",
}
]
}
My current REST handler is below. I am able to get the Id and `Version that is passed in as path params, but I am not sure how to retrieve the contents on the message body?
#PUT
#Path("/Id/{Id}/version/{version}/addPerson")
public Response addPerson(#PathParam("Id") String Id,
#PathParam("version") String version) {
if (isNull(Id) || isEmpty(version)) {
return ResponseBuilder.badRequest().build();
}
//HOW TO RECIEVE MESSAGE BODY?
//carry out PUT request and return DTO: code not shown to keep example simple
if (dto.isSuccess()) {
return Response.ok().build();
} else {
return Response.serverError().build();
}
}
Note: I am using the JAX-RS framework.
You just need to map your name json to a POJO and add #Consumes annotation to your put method, here is an example:
#PUT
#Consumes("application/json")
#Path("/Id/{Id}/version/{version}/addPerson")
public Response addPerson(#PathParam("Id") String Id,
#PathParam("version") String version,
List<NamObj> names) {
I assume you are trying to retrieve a list of elements if is not the case just use you POJO as it in the param.
Depending on what json library are you using in your server you may need to add #xml annotation to your POJO so the parser could know how to map the request, this is how the mapping for the example json should look like:
#XmlRootElement
public class NameObj {
#XmlElement public int id;
#XmlElement public String name;
#XmlElement public String type;
}
Jersey doc: https://jersey.java.net/documentation/latest/user-guide.html#json
#cosumes reference: http://docs.oracle.com/javaee/6/tutorial/doc/gilik.html#gipyt
Can someone please help me how to get a JSON String in a Webservice. I's sending JSON to my /api/register that looks like:
{"name":"MyName","surname":"MySurename","email":"mail#asd.de","street":"MyStreet","number":"3","zip":"12345","city":"myCity","pass":"myPassword"}
Here is my register.java file:
#Path("/register")
#Stateless
public class RegisterWS {
#EJB
UserBS userBS;
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void createUser(){
// code to get data from json
userBS.createUser(name, surename, email, adress, number, zip, city, password);
}
}
My AngularJS Controller and Service. The Data comes from a form, that is parsed to a JSON object.
app.service('RegisterService', function ($http) {
return {
registerUser : function(user) {
$http.post('http://localhost:8080/myApp/api/register')
.success(function (user) {
return user;
})
.error(function (data) {
// failed
});
}
}
});
app.controller('RegisterCtrl', function($scope, RegisterService) {
$scope.register = function(){
RegisterService.registerUser(angular.toJson($scope.user));
}
});
You should have a POJO, which maps to the received JSON object, for example a User class. In this case this would be a very simple Java Bean, with mostly String properties for each field in the JSON.
#XmlRootElement
public class User {
String name;
String surname;
String email;
String street;
Integer number;
String zip;
String city;
String pass;
}
Of course you would use private fields, with getters and setters, but I did not want to add clutter. By the way the #XmlRootElement is a JAXB annotation, and JAX-RS uses JAXB internally.
After you have this, you just need to change your method like this
#POST
#Consumes(MediaType.APPLICATION_JSON)
public void createUser(User user) {
...
}
You should not need to change anything on the AngularJS side, as the default for the $http.post method is JSON communication.
For your Java code, you have to add a User POJO, I dont know if you will use some persistence API or not, so the user POJO must implement serializable to output user object as JSON.
Here's a an example of REST app with EJB ... : http://tomee.apache.org/examples-trunk/rest-on-ejb/README.html
For your client app, you need to specify the content type : "Content-Type" = "application/json"
See this questions: change Content-type to "application/json" POST method, RESTful API
I have a REST API implemented using Jersey, I am using the Jackson feature for automatically serialize objects to JSON, there is a special case where I need to return a JSON string that represents an script. As the script can have different unknown structures I cannot just serialize it to an Object, that script comes from a column in a db table. At the same time I have a full Script object that contains all the information of the DB including the script string as a String property.
What I want is to tell Jersey-Jackson not to serialize (skip) the endpoint GET /script/{scriptId}, look at the code:
#Path("script")
#Produces(MediaType.APPLICATION_JSON)
public class ScriptResource {
private ScriptService service;
#GET
#Path("{scriptId}")
public String getScript(#NotNull #PathParam("scriptId") Integer scriptId) {
return service.getScript(scriptId); // returns a a valid JSON String
}
#GET
#Path("full/{scriptId}")
public Script getFullScript(#NotNull #PathParam("scriptId") Integer scriptId) {
return service.getFullScript(scriptId); // returns a Script object
}
}
The #Produces annotation is the one that triggers the automatic transformation via Jackson, I would like to configure Jackson and exlude the resource endpoint that I don't want to be converted automatically.
I don't want to:
Use Response as a return type
Change the Produces annotation to avoid Jackson
Use a Map as a return type which I would feed by parsing the String
One more option which you can consider in addition to those mentioned by #wasabi, is having a wrapper class for your string which would customize the Jackson serialization so it would not be converted to JSON. That can be done by using the combination of the #JsonValue and #JsonRawValue annotations on the getter method.
Here is an example wrapper:
public class RawJsonString {
private final String json;
public RawJsonString(String json) {
this.json = json;
}
#JsonRawValue
#JsonValue
public String getJson() {
return json;
}
}
... then your modified resource method would look as follows:
#GET
#Path("{scriptId}")
public JsonRawString getScript(#NotNull #PathParam("scriptId") Integer scriptId) {
return new JsonRawString(service.getScript(scriptId)); // returns a a valid JSON String
}
If you just want to make sure that some fields in Script class would not be serialized by Jackson, you could easily do so by annotating such fields with #JsonIgnore.
If you would like to have more control over the generated JSON, I would implement a custom JsonSerializer, and refer to it using #JsonSerialize annotation in your Script class. See this post for an example.
If you cannot modify Script class, you could also implement a MessageBodyWriter. See this post for an example.
I'm using AndroidAnnotations to build a Rest for an Android Application.
On the Serverside im using PHP, which send a json looking like :
{"tag":"register","success":0,"error":2,"msg":"User already existed","body":[]}
I have two POJOS :
User.java:
public class User implements Serializable {
private String name;
private String email;
private String password;
//getter and setter Methods
}
Response.java:
public class RegistrationResponse implements Serializable {
private String tag;
private int success;
private int error;
private String msg;
private String body;
//getter and setter Methods
}
Rest Client:
#Rest(rootUrl = "http://my.domain.com", converters = {
MappingJacksonHttpMessageConverter.class,
StringHttpMessageConverter.class, GsonHttpMessageConverter.class }, interceptors = { MyInterceptor.class })
public interface RestClient extends RestClientErrorHandling {
#Post("/user/register/{name}/{email}/{pass}")
#Accept(MediaType.APPLICATION_JSON_VALUE)
Response sendUserRegistration(User user, String name, String email,
String pass);
RestTemplate getRestTemplate();
}
Activity.java:
//User and Response are POJOs
Response result = RestClient.sendUserRegistration(user,
user.getName(),user.getEmail(),user.getPassword());
But i got an Null Pointer Exception error on Activity.java. But if i change the return value of "sendUserRegistration" function to String all work. So my "Response" POJO seems not to be converted from AndroidAnnotations.
How can i convert the Rest Response to my "Response"-POJO using AndroidAnnotations?
You don't need to return the entire response object per rest call, just set the response to your custom object. Or you can also return a JsonObject also and use gson to convert it later on.
#Rest(rootUrl = "http://my.domain.com", converters = {
MappingJacksonHttpMessageConverter.class,
StringHttpMessageConverter.class, GsonHttpMessageConverter.class }, interceptors = { MyInterceptor.class })
public interface RestClient extends RestClientErrorHandling {
#Post("/user/register/{name}/{email}/{pass}")
#Accept(MediaType.APPLICATION_JSON_VALUE)
User sendUserRegistration(User user, String name, String email,
String pass);
RestTemplate getRestTemplate();
}
then just simply call
User newUser = RestClient.sendUserRegistration(user,
user.getName(),user.getEmail(),user.getPassword());
AA relies on Spring Android RestTemplate to make the rest call. And in order to build requests and handle responses this lib uses converters. And to know which converter the RestTemplate should use, it checks the content-type response header.
As MappingJacksonHttpMessageConverter and GsonHttpMessageConverter handles only http response with content-type=application/json and your result is converted to string, I'm pretty sure you forgot to set this header in your php server. So it send the default one (ie: text/plain) which is only handle by StringHttpMessageConverter.
Also, the body field is an object in your json example, but in your POJO you declared it as a String. So parsing will fail on this point.