Updating specific part of value in hash map dynamically - java
I have a spring boot app with a HTTP post request handler. It accepts a payload that I parse and outputs a JSON. I have handled it that it needs to accept a payload of certain parameters(18).
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;
import com.google.gson.Gson;
#Validated
#RestController
public class MockController {
#Autowired
MockConfig mockconfig;
private static final Logger LOGGER = LoggerFactory.getLogger(MockController.class);
#RequestMapping(value = "/", method = RequestMethod.GET)
public String index() {
return "hello!";
}
String[] parse;
#PostMapping(value = "/")
public String payloader(#RequestBody String params ) throws IOException{
LOGGER.debug("code is hitting");
parse = params.split("\\|");
String key;
String value;
String dyn;
Map<String, String> predictionFeatureMap = mockconfig.getPredictionFeatureMap();
if(parse.length!=18) {
key = "Not_enough_parameters";
value = predictionFeatureMap.get(key);
Map<?, ?> resultJsonObj = new Gson().fromJson(value, Map.class);
}
else {
key = params;
value = predictionFeatureMap.get(key);
}
return value;
}
}
My config class is where I get the input and output from a file and put them into a hashmap.
import java.io.File;
import java.io.IOException;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import org.springframework.context.annotation.Configuration;
#Configuration
public class MockConfig {
private Map<String, String> predictionFeatureMap = new HashMap<String, String>();
public Map<String,String> getPredictionFeatureMap() throws IOException {
return predictionFeatureMap;
}
public MockConfig() throws IOException {
init();
}
private Map<String, String> init() throws IOException {
Scanner sc = new Scanner (new File("src/test/resources/Payload1.txt"));
int counter = 1;
String key = "";
while (sc.hasNextLine()) {
if(counter % 2 != 0) {
key = sc.nextLine();
}else {
predictionFeatureMap.put(key, sc.nextLine());
}
counter++;
}
sc.close();
return predictionFeatureMap;
}
}
This is the key and value in the file that I'm trying to work with specifically.
Not_enough_parameters
{"status": false, "errorMessage": "Payload has incorrect amount of parts: expecting: 18, actual:8", "version": "0.97", "coreName": "Patient_Responsibility"}
(The JSON string is the response to too much or too little parameters... the paramter length should be 18.)
Example input:
ncs|56-2629193|1972-03-28|20190218|77067|6208|3209440|self|-123|-123|-123|0.0|0.0|0.0|0.0|0.0|0.0|0.0
This input would pass because it has 18 parameters...
What I want to do is if a user curls for example 5 parameters
ncs|56-2629193|1972-03-28|20190218|77067
I want the value(JSON error message) to have the 'actual' field updated like:
{"status": false, "errorMessage": "Payload has incorrect amount of parts: expecting: 18, actual:5", "version": "0.97", "coreName": "Patient_Responsibility"}
without hardcoding it into the txt file or hashmap...
I have tried getting the index of the string and replacing the '8' character with parse.length() and casting it as a char but it just gives me this output:
{"status": false, "errorMessage": "Payload has incorrect amount of parts: expecting:1 actual:", "version": "0.97", "coreName": "Nulogix_Patient_Responsibility"}
How do I parse or index the JSON to update this value? Or is there a hashmap method to deal with this?
When working with a framework, you usually handle errors using the frameworks way of handling errors.
To handle errors in spring boot you typically use a controller advice that will assist in handling errors. This is created by annotating a class with #ControllerAdvice.
There you can catch thrown exceptions and build responses that will be returned to the calling client.
#PostMapping(value = "/")
public String payloader(#RequestBody String params ) throws IOException{
LOGGER.debug("code is hitting");
parse = params.split("\\|");
String key;
String value;
String dyn;
Map<String, String> predictionFeatureMap = mockconfig.getPredictionFeatureMap();
if(parse.length!=18) {
// Here you throw a custom runtime exception and pass what
// parameters you want that will help you build your error
// message you are passing to your client.
final String errorMessage = String.format(
"Payload has incorrect amount of parts: expecting:%d actual:%d",
predictionFeatureMap.size(),
parse.length);
throw new MyException(errorMessage);
}
else {
key = params;
value = predictionFeatureMap.get(key);
}
return value;
}
Then in a controller advice class
#ControllerAdvice
public class Foo extends ResponseEntityExceptionHandler {
#ExceptionHandler(MyException.class)
public ResponseEntity<MyCustomErrorBody> handleControllerException(HttpServletRequest request, MyException ex) {
// Build your error response here and return it.
// Create a class that will represent the json error body
// and pass it as body and jackson will deserialize it for
// you into json automatically.
final MyCustomErrorBody body = new MyCustomErrorBody(false, ex.getMessage(), "0.97", "Patient_Responsibility")
return ResponseEntity.unprocessableEntity().body(myCustomErrorBody).build();
}
}
public class MyCustomErrorBody {
private boolean status;
private String errorMessage;
private String version;
private String coreName;
// constructor and getters setters ommitted
}
Links about spring boot error handling:
Official spring boot documentation
Baeldung exception-handling-for-rest-with-spring
Related
Map JSON string or JSON array to String in Java object [duplicate]
This question already has answers here: Make Jackson interpret single JSON object as array with one element (3 answers) Deserializing json to pojo where json field has different data types (2 answers) Closed 1 year ago. I have a JSON created by Elixir class which has a field which can be string or array: field :logs, {:array, :string} If anyone doesn't get this it will be like {"logs" : "some log 1"} or { "logs": ["some log 1", "some log 2"] } I have a Java field mapped for this: #JsonProperty("logs") private String logs; This mapping works only when the logs comes as a String, but fails if the logs comes as array with error saying it will not be able to convert START_ARRAY to string. How to serialize the field if it comes as array and store it as a comma separated string?
I see in tags that you use Jackson for parsing. This means you need to write and register with Jackson a custom deserializer for your logs field. An example of such solution: package tmp; import java.io.IOException; import java.util.Spliterator; import java.util.Spliterators; import java.util.stream.Collectors; import java.util.stream.StreamSupport; import com.fasterxml.jackson.annotation.JsonProperty; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.DeserializationContext; import com.fasterxml.jackson.databind.JsonDeserializer; import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.annotation.JsonDeserialize; import com.fasterxml.jackson.databind.exc.MismatchedInputException; import com.fasterxml.jackson.databind.node.ArrayNode; import com.fasterxml.jackson.databind.node.ValueNode; public class JacksonDemo { public static class LogHolder { #JsonProperty("logs") #JsonDeserialize(using = ArrayOrStringJsonDeserializer.class) private String logs; #Override public String toString() { return "LogHolder(logs=" + logs + ")"; } } public static class ArrayOrStringJsonDeserializer extends JsonDeserializer<String> { #Override public String deserialize(JsonParser jsonParser, DeserializationContext ctxt) throws IOException, JsonProcessingException { JsonNode node = (JsonNode) jsonParser.readValueAsTree(); if (node.isValueNode()) { ValueNode valueNode = (ValueNode) node; if (valueNode.isTextual()) { return valueNode.textValue(); } } else if (node.isArray()) { ArrayNode arrayNode = (ArrayNode) node; return StreamSupport.stream(Spliterators.spliteratorUnknownSize(arrayNode.iterator(), Spliterator.ORDERED), false) .map(JsonNode::textValue) .collect(Collectors.joining(", ")); } throw MismatchedInputException.from(jsonParser, String.class, "Expected node to be of type String or array, but got " + node.getNodeType().toString()); } } public static void main(String args[]) throws Exception { String[] docs = { "{\"logs\" : \"some log 1\"}", "{\"logs\": [\"some log 1\", \"some log 2\"]}" }; ObjectMapper om = new ObjectMapper(); for (String doc : docs) { System.out.println(om.readValue(doc, LogHolder.class)); } } } Result of executing this code: LogHolder(logs=some log 1) LogHolder(logs=some log 1, some log 2)
jsonPath cast issue in Junit5 spring boot with MockMVC
I have the below test case with imports as import org.springframework.http.MediaType; import org.springframework.test.context.junit.jupiter.SpringExtension; import org.springframework.test.web.servlet.MockMvc; import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.*; import static org.assertj.core.internal.bytebuddy.matcher.ElementMatchers.is; import static org.mockito.Mockito.doReturn; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.*; #Test #DisplayName("Should return product based on the specified Id") void shouldReturnProductBasedOnTheSpecifiedId() throws Exception { String Id = java.util.UUID.randomUUID().toString(); ProductViewModel productViewModel = new ProductViewModel(Id, "Product 1", 100, "Product 1 description", 0); doReturn(productViewModel).when(productService).findById(Id); mockMvc.perform(get(String.format("/api/v1/product/%s", Id))) //Validate the response code and content type .andExpect(status().isOk()) .andExpect(content().contentType(MediaType.APPLICATION_JSON_VALUE)) //validate the headers .andExpect(header().string(HttpHeaders.ETAG, String.format("\"%s\"", Id))) .andExpect(header().string(HttpHeaders.LOCATION, String.format("/%s", Id))) //Validate the return fields .andExpect(jsonPath("$.id", is(Id))); //.andExpect((ResultMatcher) jsonPath("$.name", is("Product 1"))) //.andExpect((ResultMatcher) jsonPath("$.price", is(100))) //.andExpect((ResultMatcher) jsonPath("$.description", is("Product 1 description"))) //.andExpect((ResultMatcher) jsonPath("$.version", is(0))); } Getting an error as If I cast the object I get an cast error message.
There are several ways to solve it: Include individual Json properties comparison import org.springframework.test.web.servlet.MockMvc; import static org.springframework.http.MediaType.APPLICATION_JSON; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.content; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.jsonPath; import static org.hamcrest.core.Is.is; mockMvc.perform(get(String.format("/api/v1/product/%s", Id)) .andExpect(content().contentType(APPLICATION_JSON_VALUE)) .andExpect(jsonPath("$.id", is(Id))); The difference with your example is on "is import". Deserialize Json response into a class and compare objects This is a more generic and reusable approach. Use a Json deserialize method to convert that one into an object of a well-known class instance. Compare expected object with the received one in the test. You can see a complete example of it in the following link, more specifically in the test: static Stream<Arguments> findByIdWithOrderLines_validIdTestCases() { PizzaDto pizzaDto = new PizzaDto((short)1, "Carbonara", 7.50); OrderLineDto orderLineDto = new OrderLineDto(10, 1, pizzaDto, (short)2, 15D); OrderDto dto = new OrderDto(1, "Order 1", new Date(), asList(orderLineDto)); return Stream.of( //#formatter:off // serviceResult, expectedResultHttpCode, expectedBodyResult Arguments.of( empty(), NOT_FOUND, null ), Arguments.of( of(dto), OK, dto ) ); //#formatter:on } #ParameterizedTest #SneakyThrows #WithMockUser(authorities = {Constants.ROLE_ADMIN}) #MethodSource("findByIdWithOrderLines_validIdTestCases") #DisplayName("findByIdWithOrderLines: when given Id verifies the validations then the suitable Http code is returned") public void findByIdWithOrderLines_whenGivenIdVerifiesValidations_thenSuitableHttpCodeIsReturned(Optional<OrderDto> serviceResult, HttpStatus expectedResultHttpCode, OrderDto expectedBodyResult) { // Given Integer validOrderId = 1; // When when(mockOrderService.findByIdWithOrderLines(validOrderId)).thenReturn(serviceResult); ResultActions result = mockMvc.perform(get(RestRoutes.ORDER.ROOT + "/" + validOrderId + RestRoutes.ORDER.WITH_ORDERLINES)); // Then result.andExpect(status().is(expectedResultHttpCode.value())); assertEquals(expectedBodyResult, fromJson(result.andReturn().getResponse().getContentAsString(), OrderDto.class)); verify(mockOrderService, times(1)).findByIdWithOrderLines(validOrderId); }
WARNING: Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json' not supported]
Hi Guys Please advice me on how to resolve this issue I am trying to consume a rest web service see the code below import java.sql.ResultSet; import java.util.Date; import java.util.Map; import javax.ws.rs.Consumes; import javax.ws.rs.Produces; import org.springframework.http.MediaType; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestBody; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.ResponseBody; import org.springframework.web.bind.annotation.RestController; import com.cwg.entrust.entities.InputString; import com.cwg.entrust.entities.TokenObject; import com.cwg.entrust.services.MyConnectionProvider; import com.cwg.entrust.services.TolenDAO; import com.mysql.jdbc.Connection; import com.mysql.jdbc.PreparedStatement; import com.mysql.jdbc.Statement;[![enter image description here][3]][3] #RestController #RequestMapping("/test") public class TfaServiceController implements TolenDAO { java.sql.Connection con = null; java.sql.PreparedStatement ps = null; Date date = new Date(); String the_date = date.toString(); #PostMapping(value = { "/validateToken" }, consumes = { MediaType.APPLICATION_JSON_VALUE } , produces = { MediaType.APPLICATION_JSON_VALUE }) public Boolean getIsValidToken(#RequestBody Map<String, String> json_Input) throws Exception { String str = json_Input.get("str1") ; String token = json_Input.get("str2") ; Boolean result = false; if (str.equalsIgnoreCase(token)) { result = true; } return result; } } see the payload below { "str1": "test one", "str2": "two test" } Both Content-Type and Accept on Postman are set to application/json But we keep getting below error WARNING: Resolved [org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'application/json' not supported] Kindly advice me on how to consume this webservice without issues Thanks all.
Since you are using the #RestController annotation at the class level , you do not have to use the #ResponseBody annotation at the method level to indicate that it is a Rest endpoint and that the response type of the controller method will be a json(by default for Rest in springboot) .Change your controller method to : #RequestMapping(value = "/validateToken", method = RequestMethod.POST) public Boolean getIsValidToken(#RequestBody Map<String, String> json_Input) throws Exception { String str = json_Input.get("str1") ; String token = json_Input.get("str2") ; Boolean result = false; if (str.equalsIgnoreCase(token)) { result = true; } return result; } Also instead of the #RequestMapping(value = "/validateToken", method = RequestMethod.POST) you could use the #PostMapping("/validateToken") annotation if your springboot version supports it .In addition to that you could specify the type of data that the endpoint expects or produces using like : #PostMapping(value = { "/validateToken" }, consumes = MediaType.APPLICATION_JSON_VALUE, produces = MediaType.APPLICATION_JSON_VALUE ) public Boolean getIsValidToken(#RequestBody Map<String, String> json_Input) throws Exception { String str = json_Input.get("str1") ; String token = json_Input.get("str2") ; Boolean result = false; if (str.equalsIgnoreCase(token)) { result = true; } return result; } Note : The consumes/produces can also be used with #RequestMapping.
This issue happened to me too. It worked when I introduced the type String before the property name (json_Input in your case) and don't when I tried with my custom type. At the end it was that I was referencing with the types of the properties instead of String type(as I am using mongodb). So, Instead of #DBRef private CustomType customProperty use: #DBRef private String customProperty Hope it helps!
Pretty JSON import when filtering but not when returning whole lot + ugly brackets in ID
I'm trying to achieve these 2 things: Method getData() to return nicely formed JSON like getById() & getBetween return already. How to get rid of those ugly brackets (original csv file I'm reading from comes with them) around ID so I could return UUID for Id, rather than a String as I currently do. Here's the code: import java.io.InputStreamReader; import java.time.LocalDate; import java.util.List; import java.util.stream.Collectors; import com.opencsv.bean.CsvToBean; import com.opencsv.bean.CsvToBeanBuilder; import org.springframework.http.HttpMethod; import org.springframework.stereotype.Service; import org.springframework.web.client.RestTemplate; import com.foobar.hotovo.Domain.PricePaid; import com.foobar.hotovo.Exceptions.PriceNotFoundException; #Service public class MainService { private static final String URL = "http://prod.publicdata.landregistry.gov.uk.s3-website-eu-west-1.amazonaws.com/pp-monthly-update-new-version.csv"; private List<PricePaid> getData() { RestTemplate restTemplate = new RestTemplate(); return restTemplate.execute(URL, HttpMethod.GET, null, clientHttpResponse -> { InputStreamReader reader = new InputStreamReader(clientHttpResponse.getBody()); CsvToBean<PricePaid> csvToBean = new CsvToBeanBuilder<PricePaid>(reader) .withType(PricePaid.class) .withSeparator(',') .withIgnoreLeadingWhiteSpace(true) .build(); return csvToBean.stream().collect(Collectors.toList()); }); } private boolean isBetween(PricePaid pricePaid, LocalDate from, LocalDate to) { LocalDate date = pricePaid.getDateOfTransfer(); return date.isAfter(from) && date.isBefore(to); } public List<PricePaid> getAll() { return getData(); } public PricePaid getById(String id) throws PriceNotFoundException { return getData().stream() .filter(pricePaid -> pricePaid.getId().equals(id)) .findFirst() .orElseThrow(() -> new PriceNotFoundException("Item not found!")); } public List<PricePaid> getBetween(LocalDate from, LocalDate to) { return getData().stream() .filter(pricePaid -> isBetween(pricePaid, from, to)) .collect(Collectors.toList()); } } Here's an example of the output from getData(): [{"id":"{9DBAD221-7F8E-6EB3-E053-6B04A8C0F257}","price":96000,"dateOfTransfer":"2002-05-31","postCode":"SA62 3JW","propertyType":"F","oldNew":"Y","duration":"L","paon":"THE COACH HOUSE, 29","saon":"FLAT 5","street":"ENFIELD ROAD","locality":"BROAD HAVEN","city":"HAVERFORDWEST","district":"PEMBROKESHIRE","county":"PEMBROKESHIRE","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-8683-6EB3-E053-6B04A8C0F257}","price":59500,"dateOfTransfer":"2002-12-05","postCode":"EX31 2BS","propertyType":"F","oldNew":"N","duration":"L","paon":"16","saon":"FLAT 3","street":"STICKLEPATH HILL","locality":"STICKLEPATH","city":"BARNSTAPLE","district":"NORTH DEVON","county":"DEVON","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-B238-6EB3-E053-6B04A8C0F257}","price":240000,"dateOfTransfer":"2002-02-15","postCode":"GL7 5BL","propertyType":"S","oldNew":"N","duration":"F","paon":"76","saon":"","street":"CHURCH ROAD","locality":"QUENINGTON","city":"CIRENCESTER","district":"COTSWOLD","county":"GLOUCESTERSHIRE","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-CBFB-6EB3-E053-6B04A8C0F257}","price":292500,"dateOfTransfer":"2002-09-27","postCode":"WR11 8QH","propertyType":"T","oldNew":"N","duration":"F","paon":"BIG BARN","saon":"","street":"","locality":"ULLINGTON","city":"EVESHAM","district":"WYCHAVON","county":"WORCESTERSHIRE","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-E1D3-6EB3-E053-6B04A8C0F257}","price":145000,"dateOfTransfer":"2002-01-25","postCode":"PE12 8SN","propertyType":"D","oldNew":"N","duration":"F","paon":"SILVERCROFT","saon":"","street":"RAVENS DROVE","locality":"HOLBEACH FEN","city":"SPALDING","district":"SOUTH HOLLAND","county":"LINCOLNSHIRE","ppd":"A","recordStatus":"A"},{"id":"{9DBAD222-5429-6EB3-E053-6B04A8C0F257}","price":79950,"dateOfTransfer":"2002-07-17","postCode":"NE29 6XJ","propertyType":"S","oldNew":"N","duration":"F","paon":"54","saon":"","street":"BLUCHER ROAD","locality":"","city":"NORTH SHIELDS","district":"NORTH TYNESIDE","county":"TYNE AND WEAR","ppd":"A","recordStatus":"A"},{"id":"{9DBAD222-5451-6EB3-E053-6B04A8C0F257}","price":65000,"dateOfTransfer":"2002-11-13","postCode":"NE6 5XY","propertyType":"F","oldNew":"N","duration":"L","paon":"71","saon":"","street":"KING JOHN TERRACE","locality":"","city":"NEWCASTLE UPON TYNE","district":"NEWCASTLE UPON TYNE","county":"TYNE AND WEAR","ppd":"A","recordStatus":"A"},{"id":"{9DBAD222-5F1E-6EB3-E053-6B04A8C0F257}","price":17000,"dateOfTransfer":"2002-07-01","postCode":"SY23 5NJ","propertyType":"D","oldNew":"N","duration":"F","paon":"TYNEWYDD","saon":"","street":"","locality":"BETHANIA","city":"LLANON","district":"CEREDIGION","county":"CEREDIGION","ppd":"A","recordStatus":"A"},{"id":"{9DBAD222-7BB6-6EB3-E053-6B04A8C0F257}","price":33000,"dateOfTransfer":"2002-01-31","postCode":"HD3 4QJ","propertyType":"T","oldNew":"N","duration":"L","paon":"26 - 28","saon":"","street":"SCAR LANE","locality":"","city":"HUDDERSFIELD","district":"KIRKLEES","county":"WEST YORKSHIRE","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-5212-6EB3-E053-6B04A8C0F257}","price":127000,"dateOfTransfer":"2002-11-28","postCode":"BS6 5QZ","propertyType":"T","oldNew":"N","duration":"F","paon":"200","saon":"","street":"CHELTENHAM ROAD","locality":"","city":"BRISTOL","district":"CITY OF BRISTOL","county":"CITY OF BRISTOL","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-65C4-6EB3-E053-6B04A8C0F257}","price":105000,"dateOfTransfer":"2002-11-01","postCode":"PE19 7BH","propertyType":"D","oldNew":"Y","duration":"F","paon":"287A","saon":"","street":"GREAT NORTH ROAD","locality":"EATON FORD","city":"ST NEOTS","district":"HUNTINGDONSHIRE","county":"CAMBRIDGESHIRE","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-79A7-6EB3-E053-6B04A8C0F257}","price":365000,"dateOfTransfer":"2002-05-31","postCode":"LA23 2HB","propertyType":"D","oldNew":"N","duration":"F","paon":"30","saon":"","street":"CRAIG WALK","locality":"","city":"WINDERMERE","district":"SOUTH LAKELAND","county":"CUMBRIA","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-8270-6EB3-E053-6B04A8C0F257}","price":58000,"dateOfTransfer":"2002-05-13","postCode":"SA62 3JW","propertyType":"F","oldNew":"Y","duration":"L","paon":"THE COACH HOUSE, 29","saon":"FLAT 3","street":"ENFIELD ROAD","locality":"BROAD HAVEN","city":"HAVERFORDWEST","district":"PEMBROKESHIRE","county":"PEMBROKESHIRE","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-9E52-6EB3-E053-6B04A8C0F257}","price":173000,"dateOfTransfer":"2002-09-16","postCode":"BN27 4BP","propertyType":"D","oldNew":"N","duration":"F","paon":"SUNNYSIDE","saon":"","street":"HACKHURST LANE","locality":"LOWER DICKER","city":"HAILSHAM","district":"WEALDEN","county":"EAST SUSSEX","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-A6F1-6EB3-E053-6B04A8C0F257}","price":110200,"dateOfTransfer":"2002-02-28","postCode":"RM16 6LW","propertyType":"F","oldNew":"Y","duration":"L","paon":"5","saon":"","street":"SAN MARCOS DRIVE","locality":"CHAFFORD HUNDRED","city":"GRAYS","district":"THURROCK","county":"THURROCK","ppd":"A","recordStatus":"A"},{"id":"{9DBAD221-B31F-6EB3-E053-6B04A8C0F257}","price":475000,"dateOfTransfer":"2002-03-28","postCode":"GL50 4LB","propertyType":"D","oldNew":"Y","duration":"F","paon":"PARK WAY","saon":"","street":"WEST DRIVE","locality":"","city":"CHELTENHAM","district":"CHELTENHAM","county":"GLOUCESTERS
You could use a library like Gson or Jackson to pretty print the json string: Gson method Jackson method
Missing steps when running feature file in IntelliJ
Intellij keeps saying Undefined Step when running my feature file. However, I have copied the steps and put them into another package and added that package name in the "glue" parameter for Edit configurations. Still not working. I've added the feature file and it doesn't show any missing step references. I am adding a screenshot. I have added all the steps in another package. Please see below The code for CountriesSteps is as follows package Steps; import Fixtures.Countries; import cucumber.api.java.en.Given; import cucumber.api.java.en.Then; import cucumber.api.java.en.When; import org.junit.Assert; public class CountriesSteps { Countries countriesclass = new Countries(); #Given("^I generate a restful request for countries$") public void iGenerateARestfulRequestForCountries() throws Throwable { countriesclass.GetCountries(); } #When("^I receive a successful country response (.*)$") public void iReceiveASuccessfulCountryResponseResponse(int code) throws Throwable { Assert.assertEquals(code, countriesclass.getsCode()); } #When("^I receive a successful country response$") public void iReceiveASuccessfulCountryResponse() throws Throwable { Assert.assertEquals(200, countriesclass.getsCode()); } #Then("^the api country response returns (.*)$") public void theApiCountryResponseReturnsCountries(int countries) throws Throwable { Assert.assertEquals(countries, countriesclass.getCount()); } #Then("^the api country response returns (.*),(.*),(.*),(.*),(.*)$") public void theApiCountryResponseReturnsCountriesNameCapitalPopulation(int countries, int index, String name, String capital, int population) throws Throwable { Assert.assertEquals(countries, countriesclass.getCount()); } #Then("^the api country response for Index (.*) returns (.*),(.*),(.*)$") public void theApiCountryResponseForIndexIndexReturnsNameCapitalPopulation(int index, String name, String capital, int population) throws Throwable { //Validate a few values from response Assert.assertEquals(name, countriesclass.getcList().get(index).name); Assert.assertEquals(capital, countriesclass.getcList().get(index).capital); Assert.assertEquals(population, countriesclass.getcList().get(index).population); } } And code for Countries is package Fixtures; import Models.CountriesData; import com.jayway.restassured.response.Response; import gherkin.deps.com.google.gson.Gson; import gherkin.deps.com.google.gson.reflect.TypeToken; import org.json.JSONArray; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; import static com.jayway.restassured.RestAssured.get; public class Countries { private static String url; private static int count; private static int sCode; private static List<CountriesData> cList; public void GetCountries() throws Exception { try { url = "http://restcountries.eu/rest/v1/all"; // make get request to fetch json response from restcountries Response resp = get(url); //Fetching response in JSON as a string then convert to JSON Array JSONArray jsonResponse = new JSONArray(resp.asString()); count = jsonResponse.length(); // how many items in the array sCode = resp.statusCode(); // status code of 200 //create new arraylist to match CountriesData List<CountriesData> cDataList = new ArrayList<CountriesData>(); Gson gson = new Gson(); Type listType = new TypeToken<List<CountriesData>>() {}.getType(); cDataList = gson.fromJson(jsonResponse.toString(), listType); cList = cDataList; } catch (Exception e) { System.out.println("There is an error connecting to the API: " + e); e.getStackTrace(); } } //getters to return ('get) the values public int getsCode() { return sCode; } public int getCount() { return count; } public List<CountriesData> getcList() { return cList; } }
When creating a new step definition file, IntelliJ by default proposes file path of \IdeaProjects\RestAPI\src\main\resources\stepmethods. Your step definition folder is \IdeaProjects\RestAPI\src\test\java\Steps. Make sure cucumber isn't looking in the wrong place.