I created a class from a json template with http://www.jsonschema2pojo.org/ and I use Genson to map my json with a Jersey based WS.
This is the first lines of my "json class" :
#JsonPropertyOrder({
"public_key",
"template",
"signature",
"due_date",
"fulfillment_date",
"template_lang_code",
"clients_id",
"electronic_invoice",
"is_draft",
"recurring_time",
"comment",
"currency",
"items",
"payment_method",
"ts"
})
public class CreateInvoiceBean {
...
...
I have getters and setters also in my class too.
I have created a restfull Ws to handle post requests and i tried to send jsons object with firefox RESTClinent plugin.
This is the first lines of my json object that i tried to send:
{
"public_key": "7f566499549fc9e6d9cc69ca3b10d5f5",
"template": "billingo",
"signature": "9273882e8b3bc7f57e1ef3bc10041bc4bf9d835c152a1e0b810b77b3d51864ad",
"due_date": "2015-10-30",
...
...}
My WS Post handler method looks like this:
#POST
#Path("/invoice")
#Consumes("application/json")
#Produces("application/json")
public String createInvoice(CreateInvoiceBean newBillingoInvoice) {
LOG.info("invoicenum:. " + newBillingoInvoice.getDueDate());
return newBillingoInvoice.getDueDate();
}
My request arrives, and the createInvoice() method invoked but if I call newBillingoInvoice.getDueDate() it's return null, but when I call newBillingoInvoice.getSignature() it's returning with the value that I sent in the request json.. And so on.. if I call newBillingoInvoice.getXY(); returns null and if I call newBillingoInvoice.getOtherSomething(); return with value.. etc..
My question is, how could it happen that one property is null and the other is not null in the same object? When I create the request I set all properties no one of them was null.
Please help me!
Thank you!
It is due to the name I think. In your json we can see that you use underscore insead of upper case at word boundaries. Like due_date instead of dueDate. And I suppose that the properties in your code follow the usual java naming convetion with upper case.
One solution would be to annotate with #JsonProperty those set and get methods to change the name from "dueDate" to "due_date".
BTW the generated code is not for Genson, JsonPropertyOrder isn't a Genson annotation.
Related
I am using Spring Boot to build a simple API that retrieves an object named MutualFund.
I have a get request that returns a MutualFund object. As I tested this method using postman, I receive a 200 status and a value of 1 in the response body. Literally a 1. Not in quotes. The value 1
I want the MutualFund object to be shown in the response body like:
{
"name": "someFund",
"price": 2.00
}
This is my controller:
#RestController
public class MutualFundController {
#Autowired
MutualFundRepo repo;
#GetMapping("/mutualFundNav/{name}")
MutualFund getMutualFundByName(#PathVariable String name) {
return repo.findByName(name);
}
}
Quick tip, the URL I use for the GET request is
localhost:8080/mutualFundNav/BenjaminFranklin
In my case, "BenjaminFranklin" is the name of the mutual fund
I fixed the mistake by using a space between BenjaminFranklin. Like this:
localhost:8080/mutualFundNav/Benjamin Franklin
I was unaware that my API returns a 200 when an object is null. I thought the object existed, and I assumed the mistake occurred due to the controller
The object is saved like this:
MutualFund mutualFund1 = new MutualFund("Benjamin Franklin", 250.00);
I have a spring rest API that returns a JSON response from the response class shown below:
public class myResponse {
private String anyString;
private boolean isBoolean;
//getters and setters
}
I am expecting the JSON response to be:
{
"anyString" : "foo",
"isBoolean" : true
}
However, whenever I inspect the browser for the response obtained, I get:
{
"anyString" : "foo",
"boolean" : true
}
Why is the preceding "is" being truncated?
If you're using Spring Boot, then somewhere internally it uses Jackson to transform your object into json string.
you can dive into the logic of ObjectMapper class, but the idea is that it follows JavaBeans convention for accessing fields and getting resulting naming.
So, for boolean property named 'isSth' (via method object.isSth() ) actually represents a field 'sth' for json. If you want to strictly set the name of the field in json, use #JsonProperty annotation
My application is receiving JSON messages from a WebSocket connection.
There are different types of answers, which are formatted like that:
{
"type": "snapshot",
"product_id": "BTC-EUR",
"bids": [["1", "2"]],
"asks": [["2", "3"]]
}
or
{
"type": "l2update",
"product_id": "BTC-EUR",
"changes": [
["buy", "1", "3"],
["sell", "3", "1"],
["sell", "2", "2"],
["sell", "4", "0"]
]
}
... for example (see full API here).
Depending on the "type", I would like GSON to map a different class (e.g. Snapshot.class and l2update.class).
I have message handlers that subscribe to the WebSocket connection and I want the message to be processed by the relevant handler. For instance:
ErrorMessageHandler would manage the errors
SnapshotMessageHandler would create the initial order book
L2UpdateMessageHandler would update the order book
and so on
My problem is to dispatch the messages depending on their type.
I was thinking to convert them to the appropriate class and then call the relevant handler using a factory. I'm currently stuck at the first step, converting the JSON in Error.class or Snapshot.class depending on the "type".
How can I do that?
For Gson you could use com.google.gson.typeadapters.RuntimeTypeAdapterFactory.
Assuming you have - for example - following classes:
public class BaseResponse {
private String type, product_id;
// rest of the common fields
}
public class Snapshot extends BaseResponse {
// rest of the fields
}
public class L2Update extends BaseResponse {
// rest of the fields
}
then you would build following RuntimeTypeAdapterFactory:
RuntimeTypeAdapterFactory<BaseResponse> runtimeTypeAdapterFactory =
RuntimeTypeAdapterFactory
.of(BaseResponse.class, "type") // set the field where to look for value
.registerSubtype(L2Update.class, "l2update") // values map to 'type'
.registerSubtype(Snapshot.class, "snapshot");// value in json
Registering this with Gson will then enable automativcal instantiation of each type of responses:
Gson gson = new GsonBuilder()
.registerTypeAdapterFactory(runtimeTypeAdapterFactory).create();
and provide BaseResponse for fromJson(..) if using it , like:
gson.fromJson( json , BaseResponse.class);
NOTE: that Gson omits de- & serializing the type field. However it needs to be set in Json. Just as it is now in responses you get.
You may want to consider using a library that requires a bit less of a solid object model, at least at first. I use JsonPath for this type of thing. You could use it to at least find out the type you're dealing with:
String type = JsonPath.read(yourIncomingJson, "$.type");
and then, based on the string, do a switch statement as #ShafinMahmud suggests.
However, you could use JsonPath for the whole thing too. You could read all of the values using the path notation and know how to parse based on the type.
Adding another library to read a single value may or may not work for you but if you use it to read other values it might end up being worthwhile.
I have made a service that returns an array of UserSettings objects:
#GET
#Produces(MediaType.APPLICATION_JSON)
#Path("/")
public Response getBulkSettings(#QueryParam("fields") List<String> fields, #QueryParam("ids") List<String> ids) {
List<UserSettings> responseArr = mailerService.fetchSettings(ids,fields);
return Response.ok(responseArr).build();
}
When I make a GET request on the URL
http://localhost:8181/settings?ids=123&fields=customData,user_id
I get the following:
[
{
"id": 0,
"user_id": 123,
"customData": "testCustomDataFor123",
"deactivationDate": null
}
]
While what I want is :
[
{
"user_id": 123,
"customData": "testCustomDataFor123"
}
]
Put #JsonIgnore at the fields you don't want or its getter.
Using the annotation #JsonIgnore is a solution if you can decide on the attributes to be filtered at compile-time. In your example you want to filter at run-time, which can be achieved using techniques from your JSON library. For example, when using Genson you could do something like this:
new GensonBuilder().exclude("password").create();
However, by doing so you loose the advantage of not having to care about how your response is serialised into JSON. Therefore, I would like to suggest that you think if it is really necessary that clients can dynamically decide on the attributes to be returned. Another solution might be to use media-types other than application/json that would allow the client to request different views of the resource. Jersey distributes incoming requests using the media-type given in the Accept header to the methods in the service class. In each method you can then work with different sub-classes of your UserSettings class that exclude different attributes using the annotation #JsonIgnore.
You could do it how the other responses suggests.
Another option with JAX-RS would be to leverage another Genson feature that enables you to filter what properties should be included or excluded.
To do so register a custom Genson instance with this special Filter.
UrlQueryParamFilter filter = new UrlQueryParamFilter();
Genson genson = new GensonBuilder().useRuntimePropertyFilter(filter).create();
new ResourceConfig()
.register(new GensonJaxRSFeature().use(genson))
.register(filter);
And then in the query define the properties you want to include or exclude like that: http://localhost/foo/bar?filter=age&filter=name.
Some more explanation can be found here.
I'm new to JAX-RS + RESTEasy
What is impeding me is that the service return the JSON String without double quotes.
#Path("/hello")
public class HelloService {
#GET
#Path("say")
#Produces(MediaType.APPLICATION_JSON)
public String say() {
return "Hello";
}
}
When I call "/hello/say" it just returns Hello but what I'm expecting is "Hello"
Googled for several days. I have a piece of Javascript using JQuery which calls the service like this:
$(function(){
$.ajax({
url : "services/hello/say",
context : $('#message'),
success : function(data){
$(this).html(data);
},
error : function(xhr, ajaxOptions, thrownError){
$(this).html(xhr.status + "<br>" + thrownError);
}
});
});
And this is the result
SyntaxError: Unable to parse JSON string
Although the status is 200.
Is there a way to solve this rather than manually adding the double quotes to the string ?
Which JSON implementation are you using together with RESTeasy, Jettison or Jackson?
Just tried with Jettison, same problem. I just looked into the JSON specification and from there it is written, that a value itself is not a valid JSON response (see http://www.json.org/). Either you have an object or an array of values.
I guess that could be the problem as RESTeasy isn't sure what to do as you don't return an Object moreover a single type (e.g. String, Integer, ...).
Wonder what happen if one returns an array.
The problem isn't with the framework, but with your code. According to JAX-RS, the method signature public String say() indicates that the String you return from the method is the entity to be returned in the response. No further processing is done. I'd link the relevant docs, but jcp.org, where they used live, appears to be gone. If you want your RESTEasy to do JSON marshalling for you, you need to return a POJO.
I would suggest you to use Jackson JSON provider. You just need to add the resteasy-jackson-provider.jar in your build path of the project. Assign the annotation, #Produces("application/json") to your method in your Business Service. And you are ready to go. Cheers !!!