I'm using Spring Rest Docs to document my REST API.
I'm using mockMVC in my integrated tests and I want to document the following JSON response:
GET /api/v1/customers/3b658b39-4264-4995-99d8-90a1672a75a7
{
"id": "3b658b39-4264-4995-99d8-90a1672a75a7",
"name": "Foo",
"nickname": "Bar",
"phones": [
{
"id": "6ca3a963-bacb-4770-a470-5902b4a17b77",
"alias": "Personal Phone 1",
"countryCode": "55",
"areaCode": "34",
"number": "99999-9999"
},
{
"id": "f3a3726b-b5f8-4652-a044-7bf3d95a37de",
"alias": "Personal Phone 2",
"countryCode": "55",
"areaCode": "34",
"number": "88888-8888"
}
]
}
How can I document the list of phones above? You could use the following snippet which uses Spring REST Docs to document this API operation:
this.mockMvc.perform(
get("/api/v1/customers/3b658b39-4264-4995-99d8-90a1672a75a7")
.accept(APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("customer").withResponseFields(
fieldWithPath("id").description("Unique identifier"),
fieldWithPath("name").description("Customer full name"),
fieldWithPath("nickname").description("How the customer wants to be called")));
According to this link https://docs.spring.io/spring-restdocs/docs/current/reference/html5/#documenting-your-api-request-response-payloads-fields-json
When documenting nested through array objects, you can use like this:
this.mockMvc.perform(
get("/api/v1/customers/3b658b39-4264-4995-99d8-90a1672a75a7")
.accept(APPLICATION_JSON))
.andExpect(status().isOk())
.andDo(document("customer").withResponseFields(
fieldWithPath("id").description("Unique identifier"),
fieldWithPath("name").description("Customer full name"),
fieldWithPath("nickname").description("How the customer wants to be called"),
fieldWithPath("phones[].id").description("PHONE ID DESCRIPTION"),
fieldWithPath("phones[].alias").description("PHONE ALIAS DESCRIPTION"),
fieldWithPath("phones[].countryCode").description("PHONE COUNTRY CODE DESCRIPTION"),
fieldWithPath("phones[].areaCode").description("PHONE AREA CODE DESCRIPTION")
fieldWithPath("phones[].number").description("PHONE NUMBER DESCRIPTION")
));
Related
I have a problem with mapping a little bit more complex object, actually it maps it but only half of the object.
The object is:
{
"firstName": "John",
"lastName": "John",
"description": "Its running",
"personalWebsite": "www.asd.com",
"country": "USA",
"email": "john#john.com",
"pictureBindingModel": {
"pictureUrl": "john.com"
},
"languageBindingModels": [{
"language": "Spanish",
"languageLevelBindingModel": {
"languageLevel": "Advanced"
}
}],
"workSphereBindingModels": [{
"workSphere": "IT",
"subSphereBindingModels": [{
"subSphere": "Programming"
}]
}],
"skillBindingModels": [{
"skill": "Spring data",
"skillLevelBindingModel": {
"skillLevel": "Beginner"
}
}],
"educationBindingModels": [{
"countryBindingModel": {
"country": "USA"
},
"universityName": "Harvard",
"titleTypeBindingModel": {
"titleType": "Ph.D"
},
"educationSubject": "Java programming",
"graduationYear": 2020
}],
"certificateBindingModels": [{
"certificateSubject": "Spring master",
"awardedFrom": "Harvard",
"graduationYear": 2021
}]
}
Have a lot of nested objects which are Sets and it does the job halfway. I use "MatchingStrategies.LOOSE".
Also the binding model is filled correctly and the structure is the same as the entity!
The 3 not mapped fields:
The problem is educationBindingModels ,certificateBindingModels is Education as well as certificates in your Pojo it should be same name . Name and mapping object are different it should be same .
I am new to yodlee trying to test the app, I am making a post call with
url -->>https://developer.api.yodlee.com:443/ysl/restserver/v1/providerAccounts?providerId=10588
where 10588 is the provider id for yes bank and sending the data as
{
"field": [
{
"id": "77398",
"value": "user id"
},
{
"id": "77399",
"value": "password"
}
]}
In response I am getting
{ "errorCode": "Y400",
"errorMessage": "Invalid fields for site ...",
"referenceCode": "S1505215393036o4j27f"
}
I believe the user id and password id provided are wrong but yodlee is giving the same id for yes bank, If any one can help regarding the same??
The field Ids doesn't seem to be right. Can you try with the following login form for YES BANK (edit the value field?
Hope this helps.
{
"loginForm": {
"row": [{
"field": [{
"id": 29421,
"value": "username"
}]
},
{
"field": [{
"id": 29420,
"value": "password"
}]
}]
}
}
I am fetching data from given url in JSON format
http://api.linkedin.com/v1/people/~:(id,email-address,first-name,last-name,headline,formatted-name,picture-url,siteStandardProfileRequest,educations:(id,school-name,field-of-study,start-date,end-date,degree,activities,notes),positions:(id,title,summary,start-date,end-date,is-current,company:(id,name,type,size,industry,ticker)))?format=json
Everything works fine, But I am not getting response for education.
Sample Response -
{
"firstName": "FNAME",
"lastName": "LNNAME",
"emailAddress": "S*******#gmail.com",
"formattedName": "FNAME LNNAME",
"pictureUrl": "https:\/\/media.licdn.com\/mpr\/mprx\/0****",
"positions": {
"_total": 1,
"values": [{
"summary": "J2EE DEVELOPER",
**
**
}
}]
}, "id": "5cNYNt0sTY", "headline": "*** Consultancy", "siteStandardProfileRequest": {
"url": "https:\/\/www.linkedin.com\/profile\/view?id=********"
}
Education data is not part of the set of basic profile fields that you have access to. The complete list is available here:
https://developer.linkedin.com/docs/fields/basic-profile
I have requirement to handle json response and it is coming by rest service GET Method call.
I already have looked solutions from these links:-
http://www.journaldev.com/2315/java-json-processing-api-example-tutorial
http://answers.oreilly.com/topic/257-how-to-parse-json-in-java/
but it is not fulfill my requirements because it is small and static. I am keeping my json response in below:-
`<!--json response start -->
{
"HotelListResponse": {
"cachedSupplierResponse": {
"#cachedTime": "0",
"#candidatePreptime": "111",
"#matchedCurrency": "true",
"#matchedLocale": "true",
"#otherOverheadTime": "4",
"#supplierRequestNum": "211",
"#supplierResponseNum": "20",
"#supplierResponseTime": "405",
"#tpidUsed": "5001"
},
"cacheKey": "302c317:13443ffb599:-7712",
"cacheLocation": "10.186.168.61:7302",
"customerSessionId": "0ABAA83D-2C31-7913-4432-FFB599907714",
"HotelList": {
"#activePropertyCount": "237",
"#size": "1",
"HotelSummary": {
"#ubsScore": "1867",
"#order": "0",
"hotelId": 127092,
"name": "The Edgewater - A Noble House Hotel",
"address1": "Pier 67, 2411 Alaskan Way",
"city": "Seattle",
"stateProvinceCode": "WA",
"postalCode": 98121,
"countryCode": "US",
"airportCode": "SEA",
"supplierType": "E",
"propertyCategory": 1,
"hotelRating": 4,
"confidenceRating": 85,
"amenityMask": 6259019,
"tripAdvisorRating": 4,
"tripAdvisorReviewCount": 590,
"tripAdvisorRatingUrl": "http://www.tripadvisor.com/img/cdsi/img2/ratings/traveler/4.0-12345-4.gif",
"locationDescription": "Near Washington State Convention & Trade Center",
"shortDescription": "<p><b>Location. </b> <br />The Edgewater - A Noble House Hotel is a business-friendly hotel located in central Seattle, close to Odyssey - The Maritime Discovery Center, Washington State Convention &",
"highRate": 249,
"lowRate": 186.75,
"rateCurrencyCode": "USD",
"latitude": 47.61252,
"longitude": -122.35013,
"proximityDistance": 11.898841,
"proximityUnit": "MI",
"hotelInDestination": true,
"thumbNailUrl": "/hotels/1000000/20000/11200/11133/11133_73_t.jpg",
"deepLink": "http://travel.ian.com/index.jsp?pageName=hotAvail&cid=55505&hotelID=127092&mode=2&numberOfRooms=2&room-0-adult-total=1&room-0-child-total=1&room-0-child-0-age=3&room-1-adult-total=1&room-1-child-total=1&room-1-child-0-age=5&arrivalMonth=8&arrivalDay=4&departureMonth=8&departureDay=5&showInfo=true&locale=en_US¤cyCode=USD",
"RoomRateDetailsList": {
"RoomRateDetails": {
"roomTypeCode": 1160,
"rateCode": 1221260,
"maxRoomOccupancy": 2,
"quotedRoomOccupancy": 2,
"minGuestAge": 0,
"roomDescription": "City Lodge - Nonrefundable",
"promoId": 200803780,
"promoDescription": "7-Day Advance Purchase Special (Nonrefundable)",
"currentAllotment": 10,
"propertyAvailable": true,
"propertyRestricted": false,
"expediaPropertyId": 11133,
"rateKey": "f3525aff-9f4d-4d92-bc1c-144628fcaa30",
"nonRefundable": true,
"RateInfos": {
"#size": "1",
"RateInfo": {
"#rateChange": "false",
"#promo": "true",
"#priceBreakdown": "true",
"RoomGroup": {
"Room": [
{
"numberOfAdults": 1,
"numberOfChildren": 1,
"childAges": 3
},
{
"numberOfAdults": 1,
"numberOfChildren": 1,
"childAges": 5
}
]
},
"ChargeableRateInfo": {
"#commissionableUsdTotal": "373.5",
"#total": "441.74",
"#surchargeTotal": "68.24",
"#nightlyRateTotal": "373.5",
"#averageBaseRate": "249.0",
"#averageRate": "186.75",
"#maxNightlyRate": "186.75",
"#currencyCode": "USD",
"NightlyRatesPerRoom": {
"#size": "1",
"NightlyRate": {
"#promo": "true",
"#rate": "186.75",
"#baseRate": "249.0"
}
},
"Surcharges": {
"#size": "1",
"Surcharge": {
"#amount": "68.24",
"#type": "TaxAndServiceFee"
}
}
}
}
}
}
}
}
}
}
}
so here I am getting dynamic response based on my rest url call so how do I set this json response to my pojo.
any help would be appreciated.
Thank you in advance.
`
You could use a framework to handle all that for you; a great one is Spring.
Have a look here
Here is stackoverflow question to get you jump-started.
example from link above:
create a Controller to handle REST calls (changed to demonstrate json use):
#Controller
#RequestMapping("/kfc/brands")
public class JSONController {
#RequestMapping(value="{name}", method = RequestMethod.POST)
public #ResponseBody Shop getShopInJSON(#PathVariable String name, #RequestBody JsonNode json) {
// do stuff with the json request body (its is jackson)
JsonNode test= json.get("test");
Shop shop = new Shop();
shop.setName(name);
shop.setStaffName(new String[]{"mkyong1", "mkyong2"});
return shop;
}
}
// you could use jQuery to perform a REST call to your new controller:
$.ajax({
type: "POST",
url: "[your server]/kfc/brands",
data: {"test": "json value"},
success: function() {}
});
Try gson lib. It converts json to pojo and pojo to json.
If you have a schema for the JSON response then jsonschema2pojo would be a good tool to use. It works in a similar way that JAXB does for XML, in that it generates pojos at build time based on the schema, which you can then use at compile time.
If there isn't a schema but you are confident on the format, you could always generate the schema yourself.
Part of REST best practice is to make use of links in the responses to allow clients to navigate from one entity to another.
For example if I had a customer object type which has child account. If I was to request a customer using /customers/1 then I might provide the following response
{
"self": "http://localhost:43002/rest/v1/customers/1",
"id": 1,
"name": "Isabella Button",
"number": "000001",
"forename": "Isabella",
"surname": "Button",
"accounts": [
{
"self": "http://localhost:43002/rest/v1/accounts/1",
"id": 1,
"name": "Main Account",
"number": "000001",
"currency": "GBP",
"fromDate": "2013-01-01",
"toDate": "9999-01-01",
"createdDttm": "2013-01-01T00:00:00.000"
}
]
}
Note the self property holds the links.
However let's say I didn't want to return the accounts in the customer query, perhaps the number of accounts might be very large so I don't want to return them by default.
{
"self": "http://localhost:43002/rest/v1/customers/1",
"id": 1,
"name": "Isabella Button",
"number": "000001",
"forename": "Isabella",
"surname": "Button"
}
A resource URL for a customer's accounts could be /customers/1/accounts
However with the customer response above the client would be unable to discover the /customers/1/accounts link.
Is there a best practice for providing hyperlinks in a response that point to "child" collections of the returned resource?
One practice is to use a links element like this:
{
"self": "http://localhost:43002/rest/v1/customers/1",
"id": 1,
"name": "Isabella Button",
"number": "000001",
"forename": "Isabella",
"surname": "Button",
"links" : [
{
"rel" : "http://www.yourapi.com/rels/accounts",
"href" : "http://localhost:43002/rest/v1/customers/1/accounts"
},
{
"rel" : "http://www.yourapi.com/rels/someOtherCollection",
"href" : "http://localhost:43002/rest/v1/customers/1/someOtherCollection",
}
]
}
Or, if you find easier to construct/read the response, you can put the same links as Link http headers.
provide a links attribute like in this example http://caines.ca/blog/programming/json-is-under-defined-for-rest/
{
"links": {
"self" : { "href": "{id}" },
"up" : { "href": "{upId}" },
"children" : { "href": "{id}/children" }
}
}