Home > front end >  How to map this Json with rest template spring boot
How to map this Json with rest template spring boot

Time:06-30

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.

  • Related