简体   繁体   中英

Jackson 2 and Spring Autowired bean

I've encountered a problem with Jackson serialization for my User object. There are a few private fields with getters and setters. And everything works fine when I do something like this:

public String json() {
   MyUser user = new MyUser();
   user.setUsername("myName");

   return mapper.writeValueAsString(user); // Valid JSON
}

But i'd like to autowire User object with Spring Framework:

@Autowired
private MyUser user;

public String json() {
    System.out.println(user.getUsername()); // Property set before and it works
    return mapper.writeValueAsString(user); // Error
}

And this doesn't work. I've got an error:

com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class org.apache.juli.OneLineFormatter and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: com.piggymetrics.classes.PiggyUser$$EnhancerBySpringCGLIB$$5f23855e["targetSource"]->org.springframework.aop.target.SimpleBeanTargetSource["beanFactory"]->org.springframework.beans.factory.support.DefaultListableBeanFactory["parentBeanFactory"]->org.springframework.beans.factory.support.DefaultListableBeanFactory["beanClassLoader"]->org.apache.catalina.loader.WebappClassLoader["resources"]->org.apache.catalina.webresources.StandardRoot["context"]->org.apache.catalina.core.StandardContext["logger"]->org.apache.juli.logging.DirectJDKLog["logger"]->java.util.logging.Logger["parent"]->java.util.logging.Logger["handlers"]->org.apache.juli.AsyncFileHandler["formatter"])
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.failForEmpty(UnknownSerializer.java:59)
at com.fasterxml.jackson.databind.ser.impl.UnknownSerializer.serialize(UnknownSerializer.java:26)

And when i try to ignore these unknown errors

mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);

I got an Infinite recursion:

com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain: org.apache.catalina.core.StandardEngineValve["container"]->org.apache.catalina.core.StandardEngine["pipeline"]->org.apache.catalina.core.StandardPipeline["basic"]->org.apache.catalina.core.StandardEngineValve["container"]
...

Looks like Spring did something wrong with autowired MyUser instance so Jackson can't serialize it.

Is there a way to fix it?

UPDATE

MyUser class is pretty simple:

package com.metrics.classes;

import com.metrics.classes.interfaces.User;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Component;

@Component
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class MyUser implements User {

    private String username;

    public String getUsername() {
        return username;
    }

    public void setUsername(String username) {
        this.username = username;
    }
}

Since you use MyUser as a Spring managed bean, Spring wraps your object into a proxy - so when you are calling mapper.writeValueAsString(user); you are actually passing a proxy as argument. Said proxy contains some properties, that mapper cannot serialize.

You can try applying filter before serialization to include only the properties you need:

ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider()
    .addFilter("myUser", simpleBeanPropertyFilter.filterOutAllExcept("username"));

mapper.setFilters(filterProvider);
return mapper.writeValueAsString(user);

This exception is thrown in UnknownSerializer class. Here is the exact code which throws the exception:

throw new JsonMappingException("No serializer found for class "+value.getClass().getName()
   +" and no properties discovered to create BeanSerializer 
   (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )");

The error message appends the name of the class which it is not able to serialize. In your case, based on the error message the problem is with org.apache.juli.OneLineFormatter class. Hence, there is no problem with MyUser class.

Now coming to reason for this error, it is thrown when serializing an entity that has all fields private. In org.apache.juli.OneLineFormatter class all fields are private without any public getter and setter methods.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM