JSON decoding error when Posting to Spring Boot 2 Custom Endpoint - json

I am using Custom Endpoints with Spring Boot 2.0.4.RELEASE
I have my custom endpoint as below,
#Endpoint(id = "mycaches" ,enableByDefault=true)
#Component
public class CacheEndpoint {
#WriteOperation
public String invalidateCacheKeys(#Selector String arg0,List<String> cacheList) {
System.out.println(cacheList);
return "Success";
}
}
Basically, I want to receive a collection of keys and process them accordingly.
When I am trying to submit the request through rest client as below
[
"1","2","3"
]
I get the below error.
Response status 400 with reason "Failed to read HTTP message"; nested exception is org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize instance of `java.util.LinkedHashMap` out of VALUE_STRING token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.util.LinkedHashMap` out of VALUE_STRING token
at [Source: UNKNOWN; line: -1, column: -1]
If I submit with the below input,
{
"cacheList": ["1","2","3"]
}
I get the below error,
Response status 400 with reason "Failed to read HTTP message"; nested exception is org.springframework.core.codec.DecodingException: JSON decoding error: Cannot deserialize instance of `java.lang.String` out of VALUE_STRING token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `java.lang.String` out of VALUE_STRING token
at [Source: UNKNOWN; line: -1, column: -1] (through reference chain: java.util.LinkedHashMap["cacheList"])
Can someone help me in resolving the issue.

Related

RestTemplate postForEntity get List of DTOs

I has the same issue as mentioned in here. So I implemented my code as follows.
String url = "http://localhost:8080/admin/user/find/all/email"+"?email={email}";
ResponseEntity<List<LdapUserDto>> responseEntity = restTemplate.exchange(
url,
HttpMethod.POST,
null,
new ParameterizedTypeReference<List<LdapUserDto>>() {},
email);
Here is the DTO I used.
#Getter
#Setter
#NoArgsConstructor
#AllArgsConstructor
public class LdapUserDto {
#JsonProperty("id")
private String id;
#JsonProperty("email")
private String email;
#JsonProperty("fullName")
private String fullName;
}
The response expected from the API is as follows.
[
{
"id": "7264a0e5",
"email": "Admin#telecom.mu",
"fullName": "Administrator"
},
{
"id": "0eccd314",
"email": "ABC.John#telecom.mu",
"fullName": "ABC John"
}
]
Once I test the API, it gives me following error which I cannot understand the reason for it.
2022-08-16 01:06:48.407 DEBUG [admin,917e5c4b9e42604c,917e5c4b9e42604c] 15716 --- [nio-8080-exec-1] o.s.web.servlet.DispatcherServlet : Failed to complete request: org.springframework.web.client.RestClientException: Error while extracting response for type [java.util.List<com.cloudportal.admin.dto.response.user.LdapUserDto>] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1]
2022-08-16 01:06:48.415 ERROR [admin,917e5c4b9e42604c,917e5c4b9e42604c] 15716 --- [nio-8080-exec-1] o.a.c.c.C.[.[.[/].[dispatcherServlet] : Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.client.RestClientException: Error while extracting response for type [java.util.List<com.cloudportal.admin.dto.response.user.LdapUserDto>] and content type [application/json;charset=UTF-8]; nested exception is org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`); nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1]] with root cause
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `java.util.ArrayList<com.cloudportal.admin.dto.response.user.LdapUserDto>` from Object value (token `JsonToken.START_OBJECT`)
at [Source: (org.springframework.util.StreamUtils$NonClosingInputStream); line: 1, column: 1]
Can anyone help me to fix this issue?
I reproduced the above problem. I noticed 2 things.
i) If the response is a list of objects in your case List there is no issue .
ii) If the response is a single object then you will get the above error.
I suggest you look into how you are sending the object in this API:
http://localhost:8080/admin/user/find/all/email"+"?email={email}
P.S I wouldve added this as a comment but I am short on RP.

How do I correctly deserialize json that consists of a list item that includes another object?

The client I am using returns json like this:
[
{
"source": "ANY"
}
]
That is, the element of the array that the object is in.
I'm trying to make a request like this:
restTemplate.postForObject<AbcdResponse>(
"/address",
listOf(value).let { JsonHttpEntity(it) }
)
data class AbcdResponse(
val obj: AbcdObject
)
data class DaDataAddress(
val source: String?
)
But I get the HttpMessageNotReadableException exception:
org.springframework.http.converter.HttpMessageNotReadableException: JSON parse error: Cannot deserialize instance of `com.app.client.abcd.domain.AbcdResponse` out of START_ARRAY token; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize instance of `com.app.client.abcd.domain.AbcdResponse` out of START_ARRAY token
at [Source: (ByteArrayInputStream); line: 1, column: 1]
How can I deserialize the response correctly?
As you probably noticed, the response as a whole is a JSON array. You can tell by the square brackets [ ... ] surrounding the whole thing.
Because of this, you cannot deserialize it as an object (such as AbcdResponse). What you should do instead is use List<DaDataAddress> instead of AbcdResponse.
You don't really need AbcdResponse. What you need is to use a ParameterizedTypeReference as follows while calling the service:
restTemplate.exchange("/address",
HttpMethod.POST,
listOf(value).let { JsonHttpEntity(it) },
ParameterizedTypeReference<List<DaDataAddress>>() {})
The reason is that the service that you are calling is returning a JSON array of JSON objects.

WCF REST JSON request: Formatter exception

I have a enum as one of the parameters in my Rest API.
End Point contract:
List<Transaction> GetTransactions(int employeeID, int recordOffset, int recordLimit, TransactionType transactionType = TransactionType.All);
InputJSON Request:
{
"employeeID":"123",
"recordOffset": 0,
"recordLimit": 80,
"transactionType":"All"
}
I'm getting a 400 bad request, when i pass this input JSON with transactionType key.
Please let me know how, i should be passing an ENUM value in the json request.
public enum TransactionType
{
All = 0,
Incoming = 1,
Outgoing = 2
}
Exception Message:
The formatter threw an exception while trying to deserialize the message: There was an error while trying to deserialize parameter http://Services/2015/03:transactionType. The InnerException message was 'There was an error deserializing the object of type Entities.TransactionType. The value 'All' cannot be parsed as the type 'Int64'.'. Please see InnerException for more details
The parameter expected is an int.
You should be passing an int value of 0, 1 or 2 in the JSON request here.
Depending on how you build up your JSON request, you could add the value of the Enum you want, e.g transactionType = TransactionType.All
This way, you can actually use your Enum when building up your request to ensure you use viable values.

Cannot pass an array in request body using Api Gateway

I have an API with PUT method in AWS Api Gateway. I'm passing an object in Request Body with content type application/json
{
"uuid": "i_1",
"insiderName": "Sam Keys",
"profileImage": "https://do6gbw1x8hs3.cloudfront.net/spree/cover_images/53977/default/400.jpg",
"gender": "Female",
"fullDescription": "This is the full description",
"shortDescription": "This is the short description",
"tribes": ["Adventurer"]
}
I'm passing a key called tribes and a value as an array. But I'm getting this error:
{"message": "Could not parse request body into json: Unexpected character (\'A\' (code 65)): was expecting comma to separate Object entries\n at [Source: [B#5d62dfa1; line: 8, column: 17]"}
I believe the error is caused by the array in the request body
We had same problem ,I added a work around by changing the array of strings into pipe separated single string and converted back to array of string after the Json is parsed on the API .
IDictionary<string, string> dictionary = new Dictionary<string, string>();
foreach (KeyValuePair<string, IEnumerable<string>> reportObject in dictionary)
{
// do something with entry.Value or entry.Key
dictionary[entry.Key] = string.Join("|", reportObject.Value.Where(x => string.IsNullOrWhiteSpace(x)));
}

Could not read JSON: Unrecognized field (...), not marked as ignorable

Yeah, I know that this issue has been discussed a few times, but I didn't manage to solve my problem.
So I'm getting a JSONObject from a http-request using org.springframework.web.client.RestTemplate:
JSONObject j = RestTemplate.getForObject(url, JSONObject.class);
But I get this error:
Exception in thread "main" org.springframework.http.converter.HttpMessageNotReadableException: Could not read JSON: Unrecognized field "uri" (Class org.json.JSONObject), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream#6f526c5f; line: 2, column: 12] (through reference chain: org.json.JSONObject["uri"]); nested exception is org.codehaus.jackson.map.exc.UnrecognizedPropertyException: Unrecognized field "uri" (Class org.json.JSONObject), not marked as ignorable
at [Source: sun.net.www.protocol.http.HttpURLConnection$HttpInputStream#6f526c5f; line: 2, column: 12] (through reference chain: org.json.JSONObject["uri"])
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.readJavaType(MappingJacksonHttpMessageConverter.java:181)
at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.read(MappingJacksonHttpMessageConverter.java:173)
at org.springframework.web.client.HttpMessageConverterExtractor.extractData(HttpMessageConverterExtractor.java:94)
at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:517)
at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:472)
at org.springframework.web.client.RestTemplate.getForObject(RestTemplate.java:237)
I want to access a Rest-Api and the Json Objects can have different field names.
I already tried #JsonIgnoreProperties(ignoreUnknown=true). But this won't work...
How do I get the response into a JSONObject?
You can use this with Jackson 2.0 :
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
If your version is prior to 2.0 use :
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.configure(
DeserializationConfig.Feature.FAIL_ON_UNKNOWN_PROPERTIES, false);