Spring rest service array as property of object - json

So, here is my problem,
I have class :
Class1 {
String prop1;
int prop2;
public Class1() {
}
setters/getters
}
And antoher one:
Class2{
String prop1;
List<Class1> porp2;
public Class2(){
}
getters/setters
}
And in controller which handle request:
#RequestMapping(value = "/path", method = RequestMethod.POST)
public #ResponseBody
String saveJingle(#RequestBody Class2 class2) throws NamingException {
}
And if I send following json:
{
prop1: 'ada',
prop2: [{'prop1':'asdad', 'prop2':'gkfjg'}]
}
And I'm getting 400 Error.
How to fix this.
Thanks

My fault, this works by default as expected, I have made syntax mistake.

Related

Not able to call one Spring REST controller from another with JSON payload

How can I call one spring REST controller from another whereby passing in the required injections?
ProtectPanController.java (Actual Rest controller doing the work)
#RestController
public class ProtectPanController {
private ProtectPanService protectPanService;
public ProtectPanController(ProtectPanService protectPanService) {
this.protectPanService = protectPanService;
}
#PostMapping(value = "/pan/protect", consumes = APPLICATION_JSON_VALUE, produces = APPLICATION_JSON_VALUE)
public ResponseEntity<String> testPostMethod(#RequestBody ProtectPan protectPan) {
ResponseEntity response = protectPanService.sendProtectPanRequest(protectPan);
return response;
}
}
WORKS (Rest URL: http://localhost:9090/hosted-payments-webapp-1.0.0/pan/protect)
Payload:
{
"paymentAccountNumber": "4111111111111111",
"tenderClass": "CreditCard"
}
Response:
{
"token": "4111110PASeK1111"
}
Pan3dsLookupController.java (this controller calls above controller)
#RestController
public class Pan3dsLookupController {
#RequestMapping(value = {"/pan/3dslookup"})
public String doProtectPanAndCmpiLookup(#RequestBody ProtectPanCmpiLookup protectPanCmpiLookup) {
ProtectPan protectPan = protectPanCmpiLookup.getProtectPan();
return "forward:/pan/protect";
}
}
ProtectPanCmpiLookup.java (a wrapper around the actual object)
public class ProtectPanCmpiLookup {
private ProtectPan protectPan;
public ProtectPan getProtectPan() {
return protectPan;
}
public void setProtectPan(ProtectPan protectPan) {
this.protectPan = protectPan;
}
}
DOES NOT WORK !! (Rest URL: http://localhost:9090/hosted-payments-webapp-1.0.0/pan/3dslookup)
Payload:
{
"protectPan": {
"paymentAccountNumber": "4111111111111111",
"tenderClass": "CreditCard"
}
}
Response:
forward:/pan/protect
The reason why your code :
return "forward:/pan/protect";
works this way and give you that text:
forward:/pan/protect
is that you use RestController and response body of your method is String type:
#RequestMapping(value = {"/pan/3dslookup"})
public String <---
#RestController is a stereotype annotation that combines #ResponseBody
and #Controller.
You have to return a ModelAndView object:
return new ModelAndView("forward:/pan/protect", modelName, modelObject)
Check this post for more info

how to add custom objectMapper for a specific spring rest controller

I have two controllers in my micro service both are POST and accepts Request body as JSON, one is working fine and another one's JSON input from some othet team and it is with root class name , so I need to write custom object mapper for this later controller, could you please guys help,
please find the codes below,
#RestController
#Slf4j
public class Controller2 {
#RequestMapping(value = "/some/update", method = RequestMethod.POST)
public String updateEmd(#RequestBody final UpdateEMDRequest updateEMDRequest) throws JsonProcessingException {
updateEMDRequest.getBookingReference()); // null now
return "success";
}
}
and the sample json is as follows,
{
"UpdateEMDRequest":{
"TransactionStatus":"SUCCESS",
"UniqueTransactionReference":"046060420",
"PreAuthReference":"040520420",
"BookingReference":"8PJ",
"CarrierCode":"AS",
"TransactionMode":"Batch",
"CallBackUrl":"www.test.com/op/update",
"Offers":[
{
"Offer":{
"traveler":{
"firstName":"AHONY",
"surname":"DNEN",
"EMD":[
"081820470"
]
}
}
}
]
}
}
UpdateEMDRequest,java
#JsonInclude(Include.NON_NULL)
public class UpdateEMDRequest {
#JsonProperty("UniqueTransactionReference")
private String uniqueTransactionReference;
#JsonProperty("TransactionStatus")
private String transactionStatus;
#JsonProperty("PreAuthReference")
private String preAuthReference;
#JsonProperty("BookingReference")
private String bookingReference;
#JsonProperty("CarrierCode")
private String carrierCode;
#JsonProperty("TransactionMode")
private String transactionMode;
#JsonProperty("CallBackUrl")
private String callBackUrl;
#JsonProperty("Offers")
private List<Offers> offers;
}
So this json is not parsed properly and updateEMDRequest's properties are null always.

Spring not accepting embedded json

I am stuck with a JSON and need assistance for the same.
I've a JSON like below which I'm getting from client. i'm using Chrome rest client to pass parameters.The content-type is "application/json"
My controller and bean classes are below. When I am making a post call I'm getting 400 bad request error.Please let me what is wrong? Is there any other way to implement apart from using so many bean classes?
{
"addSurveyRequest": {
"data": {
"suveyName": "abcde",
"surveyDesc": "pqrst",
"surveyFromDate": "MM-DD-YYYY",
"surveyToDate": "MM-DD-YYYY",
"surveyOptions": [
{
"surveyOptionName": "abc",
"surveyOptionDesc": "qwerty"
},
{
"surveyOptionName": "pqr",
"surveyOptionDesc": "asdfg"
}
]
}
}
}
I've my controller like
#RequestMapping(value = "/add", method = RequestMethod.POST, consumes="application/json", produces="application/json")
public #ResponseBody String addSurvey(#RequestBody AddSurveyRequest addSurveyRequest) throws Exception
{
String surveyId=null;
logger.debug("surveyName"+addSurveyRequest.getDataDTO().getSurveyDTO().getSurveyName()+"surveyDesc "+addSurveyRequest.getDataDTO().getSurveyDTO().getSurveyDesc()+"fromdate"+addSurveyRequest.getDataDTO().getSurveyDTO().getSurveyFromDate());
}
I've my bean class like below.
public class AddSurveyRequest{
private DataDTO data;
//setteres and getters
}
public class DataDTO{
private SurveyDTO surveyDTO;
//setteres and getters
}
public class SurveyDTO {
private int surveyId;
private String surveyName;
private String surveyDesc;
private Date surveyFromDate;
private Date surveyToDate;
private List<SurveyOptionDTO> surveyOptions;
//setteres and getters
}
public class SurveyOptionDTO {
private String surveyOptionName;
private String surveyOptionDesc;
//setteres and getters
}
Any help greatly appreciated. Thanks in advance!
I would say you should change the JSON input removing the outer addSurveyRequest as you declared the AddSurveyRequest type as parameter:
{
"data": {
"suveyName": "abcde",
"surveyDesc": "pqrst",
"surveyFromDate": "MM-DD-YYYY",
"surveyToDate": "MM-DD-YYYY",
"surveyOptions": [
{
"surveyOptionName": "abc",
"surveyOptionDesc": "qwerty"
},
{
"surveyOptionName": "pqr",
"surveyOptionDesc": "asdfg"
}
]
}
}
I made the variable name's in my Java class same as JSON parameter name and it worked out for me. I got this answer from another link, missed the link.
Below are the changes I made and it worked!
public class AddSurveyRequest{
private DataDTO addSurveyRequest;
//setteres and getters
}
public class DataDTO{
private SurveyDTO data;
//setteres and getters
}

JSON.NET deserializing derived classes does not work as expected

I have been searching the forums and the JSON.NET website on this issue and from what I can see I'm correctly following the guidelines but it is not working correctly.
I'm trying to deserialize object from derived classes.
Serializing works fine, but when deserializing it tries to deserialize in to the wrong type.
I'm trying to do this with Windows Phone 8 and JSON.NET 4.5.11
I have the following classes which I am serializing:
public class MyClass : ModelBase
{
public string Title { get; set; }
[JsonProperty(TypeNameHandling = TypeNameHandling.All)]
public MyAction Action {get; set; }
}
public abstract class MyAction : ModelBase
{
[JsonIgnore()]
public abstract ActionType ActionType { get; }
public abstract void Execute();
}
public class SettingsAction : MyAction
{
public override ActionType ActionType
{
get { return ActionType.Settings; }
}
public SettingsType SettingsType {get; set; }
public override void Execute()
{
}
}
public class NoneAction : MyAction
{
public override ActionType ActionType
{
get { return ActionType.None; }
}
public override void Execute()
{
return;
}
}
I serialize it like this:
MyClass obj = new MyClass
{
Action = new SettingsAction()
};
string json = JsonConvert.SerializeObject(
obj,
Formatting.Indented,
new JsonSerializerSettings() { TypeNameHandling = TypeNameHandling.All });
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(json);
}
And it gives me the following JSON:
{
"$type": "Model.MyClass, Model",
"Title": null,
"Action": {
"$type": "Model.SettingsAction, Model",
"SettingsType": 0
}
}
As far as I can see, this is correct, I told it to include the type information and it's correctly included.
The I deserialize it like this:
using (StreamReader r = new StreamReader(stream))
{
string json = r.ReadToEnd();
MyClass obj = JsonConvert.DeserializeObject<MyClass>(json);
}
And I get the following error:
JsonSerializationException: Error setting value to 'SettingsType' on 'Model.NoneAction'
So, although the type is contained in the JSON, on serializing it's ignoring it and of course deserializing it into a different type fails.
Does anyone have an idea why it's not taking the information into account and deserialize to the correct type?
I have found the culprit:
In one of my properties I was doing this:
public MyAction Action
{
get
{
if (_Action == null) {
Action = new NoneAction();
}
return _Action;
}
set
{
if (value != _Action)
{
_Action = value;
NotifyPropertyChanged("Action");
}
}
}
The problem is in the getter, where I create a NoneAction if the obejct is null.
Apparently Json.NET calls into the getter at some point between creating the MyClass object and setting the values of the MyAction object. When it sees that the Action-property is not null, it tries to assign the values instead of overwrite the whole object.

Jersey unmarshal JSON: Last element null does not work

I am using Jersey to parse the following JSON:
{"response":{"status":"OK","campaigns":[{"id":12345,"state":"active","code":null}]}}
But I get the following error message:
java.lang.IllegalArgumentException: No more parsing elements.
If I switch the position of the fields code and state so that the resulting JSON looks like
{"response":{"status":"OK","campaigns":[{"id":12345,"code":null,"state":"active"}]}}
everything works fine. Also if I change the code-field in the first JSON to a non-null value like "code":"test", Jersey can parse this without any problems. I tried other more complex examples always getting the above mentioned error message when leaving the last field of any element of an array null.
I think I am doing something wrong, because I could not find any others having the similar problem. I already tried to implement a CustomJAXBContextResolver using other JSON notations like natural but nothing worked for me.
Any ideas?
Here are my binding classes:
#XmlRootElement
public class LoadEntityResponse {
public LoadEntityResponse() {
}
private Response response;
public Response getResponse() {
return response;
}
public void setResponse(Response response) {
this.response = response;
}
}
and
public class Response {
public Response() {
}
private String status;
private String error;
private String error_id;
private Campaign[] campaigns;
public String getStatus() {
return status;
}
public void setStatus(String status) {
this.status = status;
}
public String getError() {
return error;
}
public void setError(String error) {
this.error = error;
}
public String getError_id() {
return error_id;
}
public void setError_id(String error_id) {
this.error_id = error_id;
}
public Campaign[] getCampaigns() {
return campaigns;
}
public void setCampaigns(Campaign[] campaigns) {
this.campaigns = campaigns;
}
}
and finally
public class Campaign{
public Campaign() {
}
protected int id;
protected String code;
protected String state;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getState() {
return state;
}
public void setState(String state) {
this.state = state;
}
}
Solved: Using JacksonJsonProvider now:
...
DefaultClientConfig config = new DefaultClientConfig();
config.getClasses().add(JacksonJsonProvider.class);
...
that´s all!
You can also use Jackson POJO support that comes with jersey-json but there is a need to do some configuration, see POJO support in Jersey User Guide.
Try using Genson http://code.google.com/p/genson/.
To enable it on client side use the following code:
ClientConfig config = new DefaultClientConfig();
config.getClasses().add(GensonJsonConverter.class);
cli = Client.create(config);
EDIT: on server side there is no configuration needed, when the jar is in your classpath json support is automatically enabled.