JSON parse error: Cannot deserialize instance of `java.lang.Long - spring-boot

I am using Spring boot I try to create a new Student.
#RequestMapping(path="/student/create", method=RequestMethod.POST)<br>
public ResponseEntity<String> createStudent(#RequestBody Long nummer, String firstname, String lastname){<br>
service.createStudent(matrikelnummer, vorname, nachname);<br>
return new ResponseEntity<String>("gut gemacht", HttpStatus.OK);
Here my RequestBody with RESTCLIENT
{"nummer":15557,"firstname":"toti","lastname":"Innna"}
I have this Error:
{"timestamp":"2019-12-20T19:41:30.083+0000","status":400,"error":"Bad
Request","message":"JSON parse error: Cannot deserialize instance of
java.lang.Long out of START_OBJECT token; nested exception is
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot
deserialize instance of java.lang.Long out of START_OBJECT token\n
at [Source: (PushbackInputStream); line: 1, column:
1]","trace":"org.springframework.http.converter.HttpMessageNotReadableException:
JSON parse error: Cannot deserialize instance of java.lang.Long out
of START_OBJECT token; nested exception is
com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot
deserialize instance of java.lang.Long out of START_OBJECT token\n
at [Source: (PushbackInputStream); line: 1, column: 1]\r\n\tat

In your example the mapper expects the body to present a Long object, but you pass it a Student object. This does not match, so it throws an exception.
It is not necessary to list all the fields of the students as separate method arguments, you can just pass a Student object as RequestBody argument.
The object mapper will then try to resolve a Student instance from the provided JSON.
Example:
#RequestMapping(path="/student/create", method=RequestMethod.POST)
public ResponseEntity<String> createStudent(#RequestBody Student student){
service.createStudent(student);
return new ResponseEntity<String>("gut gemacht", HttpStatus.OK);
}

Related

Spring Data JPA Proxies for interface projection not serializable to Redis

I'm attempting to store the results of a Repository query to a Redis cache, and running into the following error:
org.springframework.data.redis.serializer.SerializationException: Could not read JSON: Cannot construct instance of `com.sun.proxy.$Proxy173` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"["java.util.ArrayList",[{"#class":"com.sun.proxy.$Proxy173","busDate":"2022-09-12","vendorMasterAccount":"emily#emilylark.com","vendor":"btlife","affiliate":"5w1ft3bg","itemNo":null,"amount":158.55,"netAmount":null,"affAmount":null,"saleCount":null},{"#class":"com.sun.proxy.$Proxy173","busDate":"2022-09-16","vendorMasterAccount":"emily#emilylark.com","vendor":"btlife","affiliate":"5w1ft3bg","itemNo":null,"amount":51.58,"netAmount":null,"affAmount":null,"saleCount":null},{"#class":"com.sun.proxy."[truncated 191979 bytes]; line: 1, column: 61] (through reference chain: java.util.ArrayList[0]); nested exception is com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.sun.proxy.$Proxy173` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"["java.util.ArrayList",[{"#class":"com.sun.proxy.$Proxy173","busDate":"2022-09-12","vendorMasterAccount":"emily#emilylark.com","vendor":"btlife","affiliate":"5w1ft3bg","itemNo":null,"amount":158.55,"netAmount":null,"affAmount":null,"saleCount":null},{"#class":"com.sun.proxy.$Proxy173","busDate":"2022-09-16","vendorMasterAccount":"emily#emilylark.com","vendor":"btlife","affiliate":"5w1ft3bg","itemNo":null,"amount":51.58,"netAmount":null,"affAmount":null,"saleCount":null},{"#class":"com.sun.proxy."[truncated 191979 bytes]; line: 1, column: 61] (through reference chain: java.util.ArrayList[0])
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:152)
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:130)
at org.springframework.data.redis.serializer.DefaultRedisElementReader.read(DefaultRedisElementReader.java:49)
at org.springframework.data.redis.serializer.RedisSerializationContext$SerializationPair.read(RedisSerializationContext.java:272)
at org.springframework.data.redis.cache.RedisCache.deserializeCacheValue(RedisCache.java:280)
at org.springframework.data.redis.cache.RedisCache.lookup(RedisCache.java:94)
at org.springframework.cache.support.AbstractValueAdaptingCache.get(AbstractValueAdaptingCache.java:58)
at com.clickbank.clientanalytics.components.WebFluxCache.lambda$lookupWithMetrics$3(WebFluxCache.java:54)
at reactor.cache.CacheMono.lambda$null$4(CacheMono.java:158)
at reactor.core.publisher.MonoDefer.subscribe(MonoDefer.java:44)
at reactor.core.publisher.InternalMonoOperator.subscribe(InternalMonoOperator.java:64)
at reactor.core.publisher.MonoFlatMap$FlatMapMain.onNext(MonoFlatMap.java:157)
at reactor.core.publisher.FluxPeek$PeekSubscriber.onNext(FluxPeek.java:199)
at reactor.core.publisher.FluxDefaultIfEmpty$DefaultIfEmptySubscriber.onNext(FluxDefaultIfEmpty.java:100)
at reactor.core.publisher.FluxMap$MapSubscriber.onNext(FluxMap.java:120)
at reactor.core.publisher.FluxSwitchIfEmpty$SwitchIfEmptySubscriber.onNext(FluxSwitchIfEmpty.java:73)
at reactor.core.publisher.Operators$ScalarSubscription.request(Operators.java:2397)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.set(Operators.java:2193)
at reactor.core.publisher.Operators$MultiSubscriptionSubscriber.onSubscribe(Operators.java:2067)
at reactor.core.publisher.MonoJust.subscribe(MonoJust.java:54)
at reactor.core.publisher.Mono.subscribe(Mono.java:4150)
at reactor.core.publisher.MonoSubscribeOn$SubscribeOnSubscriber.run(MonoSubscribeOn.java:126)
at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:84)
at reactor.core.scheduler.WorkerTask.call(WorkerTask.java:37)
at java.base/java.util.concurrent.FutureTask.run(FutureTask.java:264)
at java.base/java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:304)
at java.base/java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1130)
at java.base/java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:630)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.sun.proxy.$Proxy173` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (byte[])"["java.util.ArrayList",[{"#class":"com.sun.proxy.$Proxy173","busDate":"2022-09-12","vendorMasterAccount":"emily#emilylark.com","vendor":"btlife","affiliate":"5w1ft3bg","itemNo":null,"amount":158.55,"netAmount":null,"affAmount":null,"saleCount":null},{"#class":"com.sun.proxy.$Proxy173","busDate":"2022-09-16","vendorMasterAccount":"emily#emilylark.com","vendor":"btlife","affiliate":"5w1ft3bg","itemNo":null,"amount":51.58,"netAmount":null,"affAmount":null,"saleCount":null},{"#class":"com.sun.proxy."[truncated 191979 bytes]; line: 1, column: 61] (through reference chain: java.util.ArrayList[0])
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1615)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1332)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:331)
at com.fasterxml.jackson.databind.deser.BeanDeserializer._deserializeOther(BeanDeserializer.java:199)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:166)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer._deserializeTypedForId(AsPropertyTypeDeserializer.java:132)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromObject(AsPropertyTypeDeserializer.java:99)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:195)
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:710)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:292)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:249)
at com.fasterxml.jackson.databind.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:26)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer._deserialize(AsArrayTypeDeserializer.java:120)
at com.fasterxml.jackson.databind.jsontype.impl.AsArrayTypeDeserializer.deserializeTypedFromArray(AsArrayTypeDeserializer.java:53)
at com.fasterxml.jackson.databind.jsontype.impl.AsPropertyTypeDeserializer.deserializeTypedFromAny(AsPropertyTypeDeserializer.java:193)
at com.fasterxml.jackson.databind.deser.std.UntypedObjectDeserializer$Vanilla.deserializeWithType(UntypedObjectDeserializer.java:710)
at com.fasterxml.jackson.databind.deser.impl.TypeWrappedDeserializer.deserialize(TypeWrappedDeserializer.java:68)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4526)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3529)
at org.springframework.data.redis.serializer.GenericJackson2JsonRedisSerializer.deserialize(GenericJackson2JsonRedisSerializer.java:150)
It seems to be an issue with Jackson not knowing how to serialize proxied instances of the interface.
Repository:
public interface AccountSalesHealthRepository extends CrudRepository<AccountSalesHealth, String> {
#Query(
value = "select vendor_master_account as vendorMasterAccount" +
" , vendor" +
" , affiliate" +
" , bus_date as busDate" +
" , sum(sale_amount) as amount " +
"from mv_ca_account_sales_health " +
"where vendor_master_account = :vendorMasterAccount" +
" and bus_date >= :start" +
" and bus_date <= :end " +
"group by 1, 3, 2, 4",
nativeQuery = true
)
Collection<AccountSalesHealthDto> getGrossSalesByAffiliate(#Param("vendorMasterAccount") String vendorMasterAccount, #Param("start") String start, #Param("end") String end);
Entity model:
#Entity
#Table(name = "mv_ca_account_sales_health")
public class AccountSalesHealth {
#Id
private Integer id;
}
DTO interface:
#JsonPropertyOrder({"busDate", "vendorMasterAccount", "vendor", "affiliate", "itemNo", "amount", "netAmount"})
public interface AccountSalesHealthDto {
String getVendorMasterAccount();
String getVendor();
String getBusDate();
String getAffiliate();
String getItemNo();
Double getAmount();
Double getAffAmount();
Double getNetAmount();
Integer getSaleCount();
}
Is there any way to specify the way to create these or otherwise influence the serialization behavior?

Deserialize Long(Epoch Time) to Java Date Object using GSON

I am subscribing to an SQS and the message body has a few epoch times. It looks like below
"createdAt" : 1660744139,\n "updatedAt" : 1660744139,\n
I have a Java POJO which contains 2 fields
Date createdAt;
Date updatedAt;
I am using GSON to deserialize the SQS message body to my POJO, but it's failing with an error com.google.gson.JsonSyntaxException: 1660744139.
My JSON instantiation looks like
private static final Gson GSON = new GsonBuilder().setPrettyPrinting().create();
If I understand it right, the error is being thrown because I am trying to deserialize a Long type to Date. What will be the correct way to deserialize?
I have seen suggestions to instantiate my GSON object with dateFormatter, but not sure if that will work for my case. Thank you.

The API handles a faulty request without raising an error eventhough annotated with ApiModelProperty with dataType

I am getting the following error - "The generated value is of the type integer instead of the type ‘string’" with 42crunch conformance scan with the following problem reported - "The API handles a faulty request without raising an error"
In the test scan, it is trying to pass the following request body -
{"type":1,"visitId":"xxxx","visitorId":"Ag5w\u0010l\u0014"}
So in above request, type is passed as integer but API is declared with type with "String" property.
#ApiModelProperty(dataType = "java.lang.String", value = "Type", example = "Data")
#Pattern(regexp = "^.*$")
#Size(min = 1, max = 50)
private String type;
I have the above annotation for the input request class. So eventhough type property is declared with ApiModelProperty annotation with dataType accepting only "java.lang.String", why is it throwing error?
I also have the #Valid annotation for the controller endpoint method which is accepting the request body.
public ResponseEnvelope recommendedProducts(
#Valid #RequestBody RecommendedProductRequest productRequest,
HttpServletResponse httpServletResponse) {
Please let know how to resolve this. Thanks!

NPE from Jackson trying to serializing a field that does not exists?

Here is my simple bean
#Data
#NoArgsConstructor
#AllArgsConstructor
#Builder
public class Foo {
private String firstName;
private String lastName;
public String getFullName(){
return firstName + lastName;
}
}
when this object gets serialized in Spring-boot controller with Jackson,
I get the following error
j.l.NullPointerException: null
com.example.foobar.foo.getFullName(Foo.java:28)
s.r.NativeMethodAccessorImpl.invoke0(NativeMethodAccessorImpl.java)
s.r.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
s.r.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
j.l.reflect.Method.invoke(Method.java:498)
c.f.j.d.s.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:653)
c.f.j.d.s.s.BeanSerializerBase.serializeFields(BeanSerializerBase.java:690)..
28 common frames omitted\nWrapped by: c.f.j.d.JsonMappingException: (was java.lang.NullPointerException)
(through reference chain: com.example.foobar.foo[\"fullName\"])
c.f.j.d.JsonMappingException.wrapWithPath(JsonMappingException.java:379)
c.f.j.d.JsonMappingException.wrapWithPath(JsonMappingException.java:339)
c.f.j.d.s.s.StdSerializer.wrapAndThrow(StdSerializer.java:343)
c.f.j.d.s.s.BeanSerializerBase.serializeFields(BeanSerializerBase.java:698)
c.f.j.d.s.BeanSerializer.serialize(BeanSerializer.java:155)
c.f.j.d.s.DefaultSerializerProvider.serializeValue(DefaultSerializerProvider.java:292)
c.f.j.d.ObjectWriter$Prefetch.serialize(ObjectWriter.java:1419)
c.f.j.d.ObjectWriter.writeValue(ObjectWriter.java:940)
o.s.h.c.j.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:267)...
23 common frames omitted\nWrapped by: o.s.h.c.HttpMessageNotWritableException: Could not write content: (was java.lang.NullPointerException) (through reference chain: com.example.foobar.foo[\"fullName\"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: (was java.lang.NullPointerException) (through reference chain: com.example.foobar.foo[\"fullName\"])
o.s.h.c.j.AbstractJackson2HttpMessageConverter.writeInternal(AbstractJackson2HttpMessageConverter.java:274 ..."
Here is the requestBody that I sent
{"firstName": "foo",
"lastName: null
}
Is Jackson trying to serialize fullName property ? but I have no such field declared. is this expected behavior? I am unable to find documentation that supports this behavior.
Thanks
Your guess is right, Jackson is trying to find the field name by its getter method, which it cannot find. And hence NPE.
Different solutions
use #JsonIgnore on the getFullName method.
you can disable this feature by setting this property in spring boot application.properties file
spring.jackson.mapper.use-getters-as-setters=false
If you wish to do it with the java code (If not using spring boot), you can do it with a bean declaration like this
#Bean
public Jackson2ObjectMapperBuilder objectMapperBuilder() {
Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
builder.featuresToDisable(MapperFeature.USE_GETTERS_AS_SETTERS);
return builder;
}

Unable to deserialize a field when using FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES

I am using gson for deserialization. I have a field with the name "listName" it has #Expose annotation.
When I set FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES in GsonBuilder and create Gson object using this GsonBuilder, then that field is not getting deserialized.
When I do not use FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES then that field is getting serialized.
Why is this happening?
The json field name should be "list_name" and your pojo object would have the field listName, when you are using that FieldNamingPolicy.
JSON:
{
"list_name": ""
}
POJO CLASS:
class POJO
{
String listName;
}
IF, when you do not use FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES and that field IS getting deserialized [sic]... then my guess is that your json field name is also "listName".

Resources