How do I disable fail_on_empty_beans in Jackson? - java

Using jackson 2.1, how do I disable the fail_on_empty beans that the error message seems to want me to disable?
I'm assuming this is just the simplest thing in the world, but hell it is late and I haven't been able to find a simple tutorial or anything particularly obvious from the api. SerializationFactory? Why would they make it so unintuitive and then make the error message seem so straightforward?
Although I do like the error message, I mean, it is better than an NPE.
I'm assuming there is a way to do this using annotations - but I'm not keen on using them at all for the simplistic work I'm doing!

You can do this per class or globally, I believe.
For per class, try #JsonSerialize above class declaration.
For a mapper, here's one example:
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
// do various things, perhaps:
String someJsonString = mapper.writeValueAsString(someClassInstance);
SomeClass someClassInstance = mapper.readValue(someJsonString, SomeClass.class)
The StackOverflow link below also has an example for a Spring project.
For REST with Jersey, I don't remember off the top off my head, but I believe it's similar.
Couple of links I dug up: (edited 1st link due to Codehaus shutting down).
https://web.archive.org/web/20150513164332/https://jira.codehaus.org/browse/JACKSON-201
Jackson serializationConfig

If you are using Spring Boot, you can set the following property in application.properties file.
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

If you wish to get JSON object without any extra fields - please add this annotation to your class, it worked perfect for me.
#JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
You can also add in your application.properties file this row, but it will add an extra field to your JSON.
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false

You can also get the same issue if your class doesn't contain any public methods/properties. I normally have dedicated DTOs for API requests and responses, declared public, but forgot in one case to make the methods public as well - which caused the "empty" bean in the first place.

You can also probably annotate the class with #JsonIgnoreProperties(ignoreUnknown=true) to ignore the fields undefined in the class

In Jersey Rest Services just use the JacksonFeatures annotation ...
#JacksonFeatures(serializationDisable = {SerializationFeature.FAIL_ON_EMPTY_BEANS})
public Response getSomething() {
Object entity = doSomething();
return Response.ok(entity).build();
}

T o fix this issue configure your JsonDataFormat class like below
ObjectMapper mapper = new ObjectMapper();
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
which is almost equivalent to,
mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

I don't fully understand the reason behind this exception, but for Spring Boot projects adding the following to the properties file works a treat
application.yml
spring:
jackson:
serialization:
FAIL_ON_EMPTY_BEANS: false
application.properties
spring.jackson.serialization.FAIL_ON_EMPTY_BEANS = false

In my case, I missed to write #JsonProperty annotation in one of the fields which was causing this error.

If you use org.codehaus.jackson.map.ObjectMapper, then pls. use the following lines
mapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

Adding a solution here for a different problem, but one that manifests with the same error... Take care when constructing json on the fly (as api responses or whatever) to escape literal double quotes in your string members. You may be consuming your own malformed json.

ObjectMapper mapper = new ObjectMapper();
Hi,
When I use mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false)
My json object values come '' blank in angular page mean in response
Solved with the help of only below settings
mapper.setVisibility(mapper.getSerializationConfig().getDefaultVisibilityChecker().
withFieldVisibility(JsonAutoDetect.Visibility.ANY).withGetterVisibility(JsonAutoDetect.Visibility.NONE)
.withSetterVisibility(JsonAutoDetect.Visibility.NONE)
.withCreatorVisibility(JsonAutoDetect.Visibility.NONE));

If it is a Spring App, just paste the code in config class
#Bean
public ObjectMapper getJacksonObjectMapper() {
ObjectMapper objectMapper = new ObjectMapper();
objectMapper.findAndRegisterModules();
objectMapper.configure(
com.fasterxml.jackson.databind.SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
return objectMapper;
}

I get the same error when I return InvoiceDTO as a response to the client. The problem was when I used the bean (Customer) in the DTO (InvoiceDTO). So, to solve I changed the bean (Customer) to DTO (CustomerDTO) to disable serialization and it is worked fine.

In my case I didnt need to disable it , rather I had to put this code on top of my class : (and this solved my issue)
#JsonNaming(PropertyNamingStrategy.SnakeCaseStrategy.class)//this is what was added
#Value //this was there already
#Builder//this was there already
public class NameOfClass {
//some code in here.
}

Related

Prevent spring reactive from returning date as timestamp

I know that a lot of subject exist about that but i can't find a solution that work for me so i reopened that.
I work on an application powered by Spring Reactive. When i request on an endpoint, the date return as a timestamp. I try a lot of solution to get that Date formatted as 'YYYY-MM-DD HH:MM:SS' but nothing work.
Solution i tried :
add com.fasterxml.jackson.datatype:jackson-datatype-joda to my gradle.build file
add spring.jackson.serialization.write-dates-as-timestamps=false to application.properties
But it doesn't work
Use annotation like #JsonFormat("yyyy...") work well but i prefere a global configuration because we're a team working on the project and i want to prevent error from human mistake. Change Date type to LocalDateTime work well too but need a lot of rework on the application and if we can prevent team from that it can be nice.
Someone have an idea on why that global configuration don't work on my app and how to make it work ?
You can find an example of the code just bellow. I remove variable name's for confidentiality reason.
Date is well formatted during code execution, turn into timestamp when parsed to JSON.
Router
#Override
protected RouterFunction<ServerResponse> router() {
return RouterFunctions.route()
.path(apiPrefix , builder -> builder
.GET(« /list » , myHandler::listSomeObject)
)
.build();
}
Handler
#NonNull
public Mono<ServerResponse> listSomeObject(ServerRequest request) {
return myService.listObject()
.flatMap(response -> status(HttpStatus.OK).contentType(MediaType.APPLICATION_JSON).bodyValue(response));
}
Service
Mono<List<Object>> listObject();
Object
#AllArgsConstructor
public class Object {
public final Long id;
public final Optional<Date> date;
}
By the way, in the JacksonAutoConfiguration file i can see this :
static {
Map<Object, Boolean> featureDefaults = new HashMap<>();
featureDefaults.put(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS, false);
featureDefaults.put(SerializationFeature.WRITE_DURATIONS_AS_TIMESTAMPS, false);
FEATURE_DEFAULTS = Collections.unmodifiableMap(featureDefaults);
}
so maybe the problem is not with Jackson configuration
Thanks a lot for reading
I finally find a way to solve my problem.
I have that class :
#Configuration
#EnableWebFlux
public class WebFluxConfig implements WebFluxConfigurer {...}
I figured out removing the #EnableWebFlux annotation fix my problem. Actually, that annotation override default configuration and so, that parameter :
spring.jackson.serialization.write-dates-as-timestamps=false
was overrided by the default one of WebFluxConfigurer.
Thanks for trying to help guyz and I hope it will be usefull for someone.

Consuming Hateoas: Non-matching JSON-request generated

Hello dear Stack Overflow!!! :)
I have a bit of a problem. I am attempting to consume a Hateoas-based application in a project and I'm having issues with Hateoas and it generating a faulty JSON-request for a test. I will provide some code examples!
Basically, I use a JSONconverter that tries to convert my request body(post) to JSON but it throws an error with what I actually get. Some information and code:
Here is my ObjectMapper that I am using:
ObjectMapper objectMapper = (ObjectMapper) bean;
objectMapper.registerModules(new Jackson2HalModule());
Here is my converter config where I plug the objectmapper and the supported media types:
MappingJackson2HttpMessageConverter converter = new MappingJackson2HttpMessageConverter();
converter.setSupportedMediaTypes(Arrays.asList(MediaTypes.HAL_JSON, MediaType.APPLICATION_OCTET_STREAM, MediaType.APPLICATION_JSON_UTF8));
converter.setObjectMapper(objectMapper);
Here is my RestTemplate where I plug the Jackson 2 Http Converter I just made:
#Bean
public RestTemplate uttagRestTemplate(RestTemplateBuilder builder) {
return builder.messageConverters(mappingJackson2HttpMessageConverter, new StringHttpMessageConverter(Charset.forName("UTF-8")))
Here is the test I run with the output:
mockServer.expect(requestTo(url + "/person/" + id + "/links")).andExpect(header("Content-type", MediaType.APPLICATION_JSON_UTF8.toString()))
.andExpect(header("accept", MediaType.APPLICATION_JSON_UTF8.toString()))
.andExpect(content().string(jsonConverter.toJson(Arrays.asList(link)))).andExpect(method(HttpMethod.POST)).andRespond(withSuccess());
Finally, here is my test output(don't mind the data, it's just test data):
Expected :[{"id":2112,"rel":"EZyb","href":"dspK0XickvvcMw0","type":"RaAmwWkZHlagrcQ","length":992539719,"title":"OuaRoPRClRpvprg"}]
Actual :"[{\"id\":2112,\"rel\":\"EZyb\",\"href\":\"dspK0XickvvcMw0\",\"type\":\"RaAmwWkZHlagrcQ\",\"length\":992539719,\"title\":\"OuaRoPRClRpvprg\"}]"
It seems to do something really weird with the "actual" json-generated body. I'd like to have it match my expected, but no luck.
I've tried solving this, and if I remove the MediaType.HAL_JSON from my MappingJacksonConverter somehow it works in my tests, but then I can't consume the hateoas client. I need the media type there for it to work.
I've also tried writing my expected JSON with my MappingJackson writer, but it produces the exact same expected output.
Does anybody know what's going on here and can help me with this? Do you know how I may generate correct JSON-body to get the assert to work? Frankly it's doing my head in - and choosing between functioning tests without the media type and being able to consume the hateoas application with it obviously isn't an option for me. :(
Cheers for reading if you made it this far! :) Any pointers are welcome.
I figured out what it was. With the new config, it seems that the application automatically converts to json and I didn't need to use my own jsonConverter anymore. So what was going on as basically a toJson conversion on an already jsonified object.
After removing my own jsonconverter implementation, it now functions correctly.

Strange behaviour in jackson ObjectMapper in Spring MVC application with #JsonIdentityInfo

I'm a bit confused about those things I currently see in our Spring MVC application and I hope someone can tell me what we're making wrong. Since google doesn't have an answer for me I'm sure we're making wrong.
We've a simple Spring 4.1.5.RELEASE application. Nothing special to mention about it. There is a MappingJackson2HttpMessageConverter configured to deliver JSON to the clients in RestControllers via Jackson ObjectMapper.
All entities which get serialized via jackson have the following annotation on tpe level
#JsonIdentityInfo(generator = IntSequenceGenerator.class, property = "#jsonObjectId")
Now the strange part:
There is a spring integration test which does the following (objectMapper gets autowired from the web application context, it is the same instance which converts the request paylod)
objectMapper.writeValueAsString(dummy) // generate json from dummy object
mockMvc.perform(post(...)) // make a post request with JSON payload generated
evaluate reponse
Executing the test once is okay. If I copy that test case and execute it twice then I get a 400 from the server back saying IllegalArgumentExecption -> Already had POJO for id ... Problem can be reproduced in real world application so it seems to be no test problem.
I've figured out, that on serialization process the IntSequenceGenerator which is in charge of generating the "jsonObjectId" properties gets created every time an object needs to be serialized. Ok so far. But the corrresponding counterpart, in our case the default used SimpleObjectIdResolver from jackson is always the same instance. So the second server request (the second deserialization process) leads to that exception in SimpleObjectIdResolver.
I would be very thankful if anybody could give me a hint, what we're making wrong ...
Forgot to mention: Jackson-Core 2.4.1 was used. We now upgraded to version 2.7.0 of jackson and the SimpleObjectIdResolver now gets recreated for every deserialization. This seemed to be a bug in jackson before 2.7.0.
Edit: I was able to reduce the issue to the following small test:
public class DummyTest {
private Dummy dummy = new Dummy();
#Before
public void setUp() {
dummy.setFoo("Foo");
}
#Test
public void testApp() throws Exception {
ObjectMapper mapper = new ObjectMapper();
String dummyAsJsonString = mapper.writeValueAsString(dummy);
mapper.readValue(dummyAsJsonString, Dummy.class);
mapper.readValue(dummyAsJsonString, Dummy.class);
}
}
where Dummy.class is defined as
#JsonIdentityInfo(generator = IntSequenceGenerator.class, property = "#jsonObjectId")
public class Dummy {
private String foo;
public String getFoo() {
return foo;
}
public void setFoo(String foo) {
this.foo = foo;
}
}
You will get an IllegalStateException when executing it with jackson 2.4.1

Jackson object mapper exception

I wrote a CGM server. There I used Jackson object mapper.( Not sure I used correct library: jackson-all-1.9) After running following exception occurred.
org.codehaus.jackson.map.JsonMappingException: No serializer found for
class Content and no properties discovered to create BeanSerializer
(to avoid exception, disable
SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) )
It says to disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS.
ObjectMapper mapper = new ObjectMapper();
mapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);
Again compile time exception came.
SerializationFeature cannot be resolved to a variable.
How to solve this? I think i have used wrong library.
I had the same problem when I tried to use a good looking GCM server example found at http://hmkcode.com/android-google-cloud-messaging-tutorial/
Apart from changing the keys and IDs, the only thing I had to add to make it work is the following line in front of the "public class..." line:
#JsonAutoDetect(fieldVisibility = Visibility.ANY)
I added this line in the Content.java and the POST2GCM.java file then it was all good to go! working fine!

Parsing Jersey inputstream to JacksonObject

I have a REST WS implemented using Jersey/Jackson. The method which has been implemented is PUT and it is working fine until i get an empty or null body.
After googling a bit, I realized that it is a known issue and there are couple of work arounds available. One of the work around that i found (and implemented) is using ContentRequestFilter to intercept calls, do basic checks and decide what to do.
But in that case, I have to check if the call is for that specific method. I don't like this since what if the method changes in future ?
What i want is to receive as InputStream instead of parsed JacksonObject (Its a custom POJO object created using Jackson Annotations) and parse the inputstream to do that. However, I am unable to find a reference to do that i.e., parsing a jackson object, out of input stream (based on input media type) and return the respective object.
Can someone direct me to some helpful resources or help me here ?
This is an easy way of getting the contents from a request handled by Resource. Just replace Map.class with your annotated POJO:
#POST
public void handle(String requestBody) throws IOException {
ObjectMapper om = new ObjectMapper();
Map result = om.readValue(requestBody, Map.class);
}
With this approach you are free to handle a null value in any way you find suitable.

Categories

Resources