I am using a charging API from a carrier, and the following JSON format has to be passed with the API call. I am using okHTTP library.
String telNum = "+941234567";
String pbody = "{\"amountTransaction\": {\"clientCorrelator\": \"7659\",\"endUserId\": \"tel:"+telNum+"\",\"paymentAmount\": {\"chargingInformation\": {\"amount\": 1,\"currency\": \"LKR\",\"description\": \"Test Charge\"},\"chargingMetaData\": {\"onBehalfOf\": \"IdeaBiz Test\",\"purchaseCategoryCode\": \"Service\",\"channel\": \"WAP\",\"taxAmount\": \"0\",\"serviceID\": \"theserviceid\"}},\"referenceCode\": \"REF-12345\",\"transactionOperationStatus\": \"Charged\"}}";```
The following is how the JSON needs to be formatted.
{
"amountTransaction": {
"clientCorrelator": "54321",
"endUserId": "tel:+94761234567",
"paymentAmount": {
"chargingInformation": {
"amount": 1,
"currency": "LKR",
"description": "Test Charge"
},
"chargingMetaData": {
"onBehalfOf": "IdeaBiz Test",
"purchaseCategoryCode": "Service",
"channel": "WAP",
"taxAmount": "0",
"serviceID": "null"
}
},
"referenceCode": "REF-12345",
"transactionOperationStatus": "Charged"
}
}
I get Error 400 Bad Request
Try this will format your body according to your need
try {
JSONObject jsonObject = new JSONObject(pbody);
pbody=jsonObject.toString();
} catch (JSONException e) {
e.printStackTrace();
}
OkHTTP requires RequestBody object for POST, so try this:
RequestBody body = RequestBody.create(MediaType.APPLICATION_JSON, pbody);
Request request = new Request.Builder()
.url(url)
.post(body)
.build();
Related
I'm working on the POST request to get a better understanding of RestAssured on the website https://reqres.in/
#Test
public void postTest() {
Response response = RestAssured.given()
.body("{\"name\": \"morpheus\"}"
+ "{\"job\": \"leader\"}")
.when()
.post(base_URI);
assertEquals(response.statusCode(), 201);
System.out.println(response.asPrettyString());
}
The status code is 201 which is I expected, I want to print out the JSON data that I just POST by using response.asPrettyString()
But the data returned is
{
"id": "302",
"createdAt": "2022-08-23T21:47:44.857Z"
}
instad of
{
"name": "morpheus",
"job": "leader",
"id": "324",
"createdAt": "2022-08-23T21:47:21.176Z"
}
What should I do to get the full JSON data?
Are you sure that isn't the full JSON data? Maybe the issue is your server?
I also noticed an issue in the JSON body. I would assume this is the payload you want to send?
{
"name": "morpheus",
"job": "leader"
}
I don't think there is anything wrong with your test code other than the JSON, but you can get restAssured to log the response payload and do the assertions...
#Test
public void postTest() {
RestAssured.given()
.body("{"
+ "\"name\": \"morpheus\","
+ "\"job\": \"leader\""
+ "}")
.when()
.post(base_URI)
.then().log().body()
.and().assertThat().statusCode(201);
}
The problem is you forgot add content-type=application/json to header. The correct code would be:
Response response = RestAssured.given()
.contentType(ContentType.JSON)
.body("{\n" +
" \"name\": \"morpheus\",\n" +
" \"job\": \"leader\"\n" +
"}")
.when()
.post("https://reqres.in/api/users");
assertEquals(response.statusCode(), 201);
response.prettyPrint();
Result:
{
"name": "morpheus",
"job": "leader",
"id": "257",
"createdAt": "2022-08-24T02:48:40.444Z"
}
I'm receiving JSON from REST API looks like:
{
"items": [
{
"id": 60659,
"name": "Display",
"active": true,
"account_id": 235
},
{
"id": 36397,
"name": " Mail Display",
"active": true,
"account_id": 107
}
]
}
I'm using this method to parse it:
Mono<List<Item>> getItems(String token) {
return webCLient
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(token))
.retrieve()
.bodyToMono(ItemResponse.class)
.map(ItemResponse::getResponse)
.retryBackoff(RetrySettings.RETRIES, RetrySettings.FIRST_BACKOFF, RetrySettings.MAX_BACKOFF)
.doOnError(e -> log.error("error: " + e.getCause().toString()))
Response:
public class ItemResponse {
#JsonProperty("items")
private List<Item> response;
}
But sometimes 3rd party API returns different response without top level items property and looks like:
[
{
"id": 60659,
"name": "Display",
"active": true,
"account_id": 235
},
{
"id": 36397,
"name": " Mail Display",
"active": true,
"account_id": 107
}
]
At this point my app is crashing with JSON decoding error. I used for this case:
bodyToMono(new ParameterizedTypeReference<List<Item>>() {})
But I can't always refactoring this part of code just to handle their json. How to do it in dynamical way with Spring WebFlux? Like try -> parse#1 -> catch -> parse#2. So i need to parse json in way#1 and if error occurs app should try to parse it with way#2.
You can get the response as a string .bodyToMono(String.class) and do whatever you want, with multiple try catches... but I think your best bet is to create a custom Deserializer and use it with your WebClient via ExchangeStrategies like described here: How to customize SpringWebFlux WebClient JSON deserialization?
.
class MyResponse {
List<Object> data;
MyResponse(List<Object> data) {
this.data = data;
}
}
class MyResponseDeserializer extends JsonDeserializer<MyResponse> {
#Override
public MyResponse deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
TreeNode treeNode = jsonParser.getCodec().readTree(jsonParser);
List<Object> data = new ArrayList<>();
if (treeNode.isArray()) {
// parse it as array
} else {
// parse it as object and put inside list
}
MyResponse myResponse = new MyResponse(data);
return myResponse;
}
}
And then
WebClient getWebClient() {
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule simpleModule = new SimpleModule();
simpleModule.addDeserializer(MyResponse.class, new MyResponseDeserializer());
objectMapper.registerModule(simpleModule);
ExchangeStrategies strategies = ExchangeStrategies
.builder()
.codecs(clientDefaultCodecsConfigurer -> {
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonEncoder(new Jackson2JsonEncoder(objectMapper, MediaType.APPLICATION_JSON));
clientDefaultCodecsConfigurer.defaultCodecs().jackson2JsonDecoder(new Jackson2JsonDecoder(objectMapper, MediaType.APPLICATION_JSON));
}).build();
return WebClient.builder().exchangeStrategies(strategies).build();
}
Mono<List<Item>> getItems(String token) {
return getWebClient()
.get()
.headers(httpHeaders -> httpHeaders.setBearerAuth(token))
.retrieve()
.bodyToMono(MyResponse.class)
.map(MyResponse::data)
.retryBackoff(RetrySettings.RETRIES, RetrySettings.FIRST_BACKOFF, RetrySettings.MAX_BACKOFF)
.doOnError(e -> log.error("error: " + e.getCause().toString()))
}
The rest is the same as in your example just change the class name and add appropriate fields.
And of course this is just a fast written demo and everything hardcoded and within a one method, better to have them injected
I am trying to send below code as Json array in post request , Here is my Json:
*{
"date": "2019-01-01",
"source": {
"type": "calendar"
},
"device": {
"type": "mobile"
}
}*
Here is my code
**JSONArray array1 = new JSONArray();
JSONArray array2 = new JSONArray();
JSONObject obj = new JSONObject();
JSONObject obj2 = new JSONObject();
JSONObject obj3 = new JSONObject();
obj.put("date","2019-01-01");
obj2.put("type","calendar");
obj3.put("type","mobile");
array1.put(obj2.toString());
obj.put("source",array1.toString());
obj.put("device",array2.toString());**
Now i want to send this object in post request. How do i do that?
HttpRequest request = HttpRequest.newBuilder().POST(obj)
here how can i send the "obj" in post request
Using MockMvc, as an example, will be like this:
[...]
ObjectMapper objectMapper;
MvcResult result =
mockMvc
.perform(post(URL)
.headers(headers)
.content(objectMapper.writeValueAsString(MY OBJECT)))
.andDo(print())
.andExpect(status().isCreated())
.andReturn();
I've used this example code in my tests project. I guess ObjectMapper will help you! :)
I am getting below response when I am calling an API.
Response postRequestResponse = ConnectionUtil.getwebTarget()
.property(ClientProperties.SUPPRESS_HTTP_COMPLIANCE_VALIDATION, true)
.path("bots")
.path(ReadSkillID.readSkillId())
.path("dynamicEntities").path(dynamicEntityID)
.path("pushRequests").path(pushRequestID).path(operation)
.request()
.header("Authorization", "Bearer " + ConnectionUtil.getToken())
.get();
Below output I am getting.
{
"createdOn": "2020-08-17T12:19:13.541Z",
"updatedOn": "2020-08-17T12:19:23.421Z",
"id": "C84B058A-C8F9-41F5-A353-EC2CFE7A1BD9",
"status": "TRAINING",
"statusMessage": "Request Pushed into training, on user request"
}
I have to return this output to client with an additional field in the response. How can modify the above response and make it
{
"EntityName": "NewEntity", //New field
"createdOn": "2020-08-17T12:19:13.541Z",
"updatedOn": "2020-08-17T12:19:23.421Z",
"id": "C84B058A-C8F9-41F5-A353-EC2CFE7A1BD9",
"status": "TRAINING",
"statusMessage": "Request Pushed into training, on user request"
}
I am adding this additional field here
"EntityName": "NewEntity"
How can I do that. many things I tried but got exception.
get JSON from postRequestResponse (i have no idea what framework you are using, so you have to figer it out on your own, but the Response datatype will probably have a getResponseBody or similar method returing the JSON)
add EntityName
serialize it again to json.
class YourBean {
#Autowired
private ObjectMapper objectMapper;
public void yourMethod() {
// 1
final InputStream jsonFromResponse = ...
// 2
Map dataFromResponse = objectMapper.readValue(jsonFromResponse, Map.class);
dataFromResponse.put("EntityName", "NewEntity");
// 3
final String enrichedJson = objectMapper.writeValueAsString(dataFromResponse);
}
}
enrichedJson contains EntityName and whatever comes from the API.
I am developing an API , where I receive some article related data as a POST request. The receiver I have as following:
#ApiOperation(value = "Add a new Article", produces = "application/json")
#RequestMapping(value = "/create", method = RequestMethod.POST)
public ResponseEntity createPost(#RequestBody String postContent) {
try {
// Here I need to conver the postContent to a POJO
return new ResponseEntity("Post created successfully", HttpStatus.OK);
} catch (Exception e) {
logger.error(e);
return responseHandler.generateErrorResponseJSON(e.getMessage(),
HttpStatus.INTERNAL_SERVER_ERROR);
}
}
Now it works for simple request like:
{
"id": "1",
"title": "This is the Post Title",
"body": "This is the Post Body",
"authorName": "Test",
"tagList": [
"tag-1",
"tag-2",
"tag-3"
]
}
But in real scenario I will get receive a HTML content as the value of the "body" key in request JSON, which can have "",<,> or many thing. Then the String to JSON conversion will fail. Is there any api, library or example, where I can have HTML content as the value of a JSON key.
Following is my input request where the code is failing to parse the JSON to Object:
{
"menuId": "1",
"title": "This is the Post Title",
"body": "<p style="text-align:justify"><span style="font-size:16px"><strong>Mediator pattern</strong> is a Behavioral Design pattern. It is used to handle complex communications between related Objects, helping by decoupling those objects.</span></p>",
"authorName": "Arpan Das",
"tagList": [
"Core Java",
"Database",
"Collection"
]
}
Now How I am parsing the json is like:
public Post parsePost(String content) {
Post post = new Post();
JSONParser jsonParser = new JSONParser();
try {
JSONObject jsonObject = (JSONObject) jsonParser.parse(content);
post.setMenuId((Integer) jsonObject.get(Constant.MENU_ID));
post.setTitle((String) jsonObject.get("title"));
post.setBody((String) jsonObject.get("body"));
post.setAuthorName((String) jsonObject.get("authorName"));
post.setAuthorId((Integer) jsonObject.get("authorId"));
post.setTagList((List) jsonObject.get("tag"));
} catch (ParseException e) {
e.printStackTrace();
}
return post;
}
It is giving a parse exception :
Unexpected character (t) at position 77.
The library I am using for parsing the JSON is:
<dependency>
<groupId>com.googlecode.json-simple</groupId>
<artifactId>json-simple</artifactId>
<version>1.1.1</version>
</dependency>