I'm kind of new to REST API and I have to map an endpoint that returns me this JSON:
{
"request": {
"Target": "Affiliate_Offer",
"Format": "json",
"Service": "HasOffers",
"Version": "2",
"api_key": "3225235c5633454cf60d35838cf8466f8fcf184b1360d",
"Method": "findAll",
"contain": [
"Country"
]
},
"response": {
"status": 1,
"httpStatus": 200,
"data": {
"18292": {
"Offer": {
"id": "18292",
"name": "247 Profit Formula",
"description": "<b>Description:</b> Register for a chance to earn $500 or more per day from home!<br><br>\r\n\r\n<b>Requirement:</b> First Page Submit<br><br>\r\n\r\n<b>Country(ies):</b> US<br><br>\r\n\r\n<b>Media:</b> Blog, Display, Newsletter, Social Media, Text Links<br><br>\r\n\r\n<b>Restrictions:</b> No Incentives; no Email<br><br>\r\n\r\n<b>Other:</b> None.<br><br>\r\n",
"require_approval": "0",
"require_terms_and_conditions": 0,
"terms_and_conditions": null,
"preview_url": "https://www.247profitsecret.com/formula?",
"currency": null,
"default_payout": "0.90000",
"protocol": "server",
"status": "active",
"expiration_date": "2039-01-06 04:59:59",
"payout_type": "cpa_flat",
"percent_payout": null,
"featured": null,
"conversion_cap": "0",
"monthly_conversion_cap": "0",
"payout_cap": "0.00",
"monthly_payout_cap": "0.00",
"allow_multiple_conversions": "0",
"allow_website_links": "0",
"allow_direct_links": "0",
"show_custom_variables": "0",
"session_hours": "24",
"show_mail_list": "0",
"dne_list_id": "0",
"email_instructions": "0",
"email_instructions_from": "Your List Name",
"email_instructions_subject": "Survey Takers Needed\r\nFortune 500 Companies Need You!\r\nEarn $45 Per Online Survey\r\nSimple Survey Jobs",
"enforce_secure_tracking_link": "1",
"has_goals_enabled": "0",
"default_goal_name": "",
"modified": 1634138487,
"use_target_rules": "0",
"use_payout_groups": "0",
"link_platform": null,
"is_expired": "0",
"dne_download_url": null,
"dne_unsubscribe_url": null,
"dne_third_party_list": false,
"approval_status": "approved"
},
"Country": {
"US": {
"id": "840",
"code": "US",
"name": "United States",
"regions": []
}
}
},
"17823": {
"Offer": {
"id": "17823",
"name": "American Career Guide",
"description": "<b>Description:</b> American Career Guide is your free guide to help you search jobs in your city!<br><br>\r\n\r\n<b>Requirement:</b> Email Submit<br><br>\r\n\r\n<b>Country(ies):</b> US<br><br>\r\n\r\n<b>Media:</b> Display, Email, Newsletter, Search, Text Link<br><br>\r\n\r\n<b>Restrictions:</b> 18 ; no Incentives, no Social Media<br><br>\r\n\r\n<b>Other:</b> Contact Affiliate Manager for Suppression list. <br><br>\r\n",
"require_approval": "1",
"require_terms_and_conditions": 0,
"terms_and_conditions": null,
"preview_url": "https://jobs.theamericancareerguide.com/api/offer",
"currency": null,
"default_payout": "2.40000",
"protocol": "server",
"status": "active",
"expiration_date": "2030-01-08 04:59:59",
"payout_type": "cpa_flat",
"percent_payout": null,
"featured": null,
"conversion_cap": "200",
"monthly_conversion_cap": "0",
"payout_cap": "0.00",
"monthly_payout_cap": "0.00",
"allow_multiple_conversions": "0",
"allow_website_links": "0",
"allow_direct_links": "0",
"show_custom_variables": "1",
"session_hours": "24",
"show_mail_list": "0",
"dne_list_id": "0",
"email_instructions": "1",
"email_instructions_from": "AmericanCareerGuide\r\nAmerican_Career_Guide\r\nTheAmericanCareerGuide\r\nJobsAvailable",
"email_instructions_subject": "Job Offers Are Waiting For You\r\nJobs Available - Positions Paying Up to $35/Hour\r\nHelp Wanted - Jobs Available in Your Area!\r\nHelp Wanted in Your Area - Pick Your New Job Today!\r\nLooking for a New Career? Jobs Available in Your Area!\r\nThere Are Jobs Paying $25/Hour in Your City! Search Now!",
"enforce_secure_tracking_link": "1",
"has_goals_enabled": "0",
"default_goal_name": "",
"modified": 1647550322,
"use_target_rules": "0",
"use_payout_groups": "0",
"link_platform": null,
"is_expired": "0",
"dne_download_url": null,
"dne_unsubscribe_url": null,
"dne_third_party_list": false,
"approval_status": null
},
"Country": {
"US": {
"id": "840",
"code": "US",
"name": "United States",
"regions": []
}
}
},
I have my controller with this call:
@GetMapping("/find-all-offers-api")
public ResponseEntity<OfferMapper> findAllOffersApi() {
log.info("Find All Offers From Api - Controller Call");
return service.findAllOffersApi();
}
My service implementation:
@Override
public ResponseEntity<OfferMapper> findAllOffersApi() {
log.info("Find All Offers From Api - Service Call");
HttpHeaders headers = new HttpHeaders();
headers.setAccept(List.of(MediaType.APPLICATION_JSON));
HttpEntity<String> entity = new HttpEntity<>("parameters", headers);
return restTemplate.exchange(GET_ALL_OFFERS_API, HttpMethod.GET, entity, OfferMapper.class);
}
Now I'm getting a little bit confused. I created the OfferMapper to receive all the attributes from this JSON but some properties are coming null also I don't know if creating sub-objects (OfferRequest request, OfferResponse response) is the correct way to map it.
@Data
@AllArgsConstructor
@NoArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class OfferMapper {
OfferRequest request;
OfferResponse response;
}
Here is the OfferResponse request and response:
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class OfferRequest {
private String target;
private String format;
private String service;
private String version;
private String api_key;
private String method;
private List<String> contains;
}
@Data
@NoArgsConstructor
@AllArgsConstructor
@JsonIgnoreProperties(ignoreUnknown = true)
public class OfferResponse {
private int status;
private int httpStatus;
private OfferData data;
}
When I call with postman I get this response:
{
"request": {
"target": null,
"format": null,
"service": null,
"version": null,
"api_key": "3225235c5633454cf60d35838cf8466f8fcf184b1360d",
"method": null,
"contains": null
},
"response": {
"status": 1,
"httpStatus": 200,
"data": {
"offer": null
}
}
}
The call return some values but I don't understand why Im getting those nulls values and also how I'm gonna make this part in Java because its not like a list structure the JSON does not have [] for the offers only {}:
"data": {
"18292": {
"Offer": {
"id": "18292",
"name": "247 Profit Formula",
CodePudding user response:
In your API response, you're getting this (I only use one fragment but you can extend the idea to all the other fields):
{
"request": {
"Target": "Affiliate_Offer",
"Format": "json",
However, in your POJO, you have this:
public class OfferRequest {
private String target;
private String format;
You must know that Jackson, when serializing/deserializing, will use reflection unless differently specified. That means, if you're declaring the field to be named target
, it will expect the Json to contain target
and not Target
.
Note that letting Jackson use reflection instead of using Jackson's annotations is a bad practice, because you strictly link your code to the Json they represent (which should not be the case).
In order to make your code solid, these are the things I suggest:
First, explicitly name your fields using the @JsonProperty annotation:
@JsonProperty("Target") //<-- I'm saying the serialized name of this property is Target with capital T
private String target;
Second, declare the fields final
(they are not supposed to change anyway):
private final String target; //<-- field must be initialized and can't change its value anymore
The above will force you to initialize them in the constructor. So you can create a constructor for your class, that you will annotate with @JsonConstructor
and will guide Jackson to build your class correctly:
@JsonCreator
public OfferRequest(@JsonProperty(value = "Target", required = true) String target) { //<-- you require the field Target to be present, else you stop the Json deserialization with an error
this.target = requireNonNull(target, "target should not be null");
}
Like this, you're explicitly telling to Jackson that you expect a field Target
to be in the Json and if it's not, you'll have a parse exception.
Also, the Objects.requireNonNull()
is your way to check that the field should not be null
(because if the Json contains "Target": null
, Jackson will see the field and will let it pass anyway).
CodePudding user response:
Try @SerializedName("Field_name") for field that start's By uppercase(Target, Format...)
@SerializedName("Target")
private String target;
I think after this changes 'u can get values.