Jackson 2 和 Spring Autowired bean
Jackson 2 and Spring Autowired bean
我的用户对象的 Jackson 序列化遇到了问题。
有一些带有 getter 和 setter 的私有字段。当我这样做时一切正常:
public String json() {
MyUser user = new MyUser();
user.setUsername("myName");
return mapper.writeValueAsString(user); // Valid JSON
}
但我想使用 Spring 框架自动装配用户对象:
@Autowired
private MyUser user;
public String json() {
System.out.println(user.getUsername()); // Property set before and it works
return mapper.writeValueAsString(user); // 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$f23855e["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)
当我试图忽略这些未知错误时
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
我得到了一个无限递归:
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (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"]
...
看起来 Spring 对自动装配的 MyUser 实例做了一些错误,因此 Jackson 无法序列化它。
有办法解决吗?
更新
MyUser class 非常简单:
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;
}
}
由于您使用 MyUser
作为 Spring 托管 bean,Spring 将您的对象包装到代理中 - 所以当您调用 mapper.writeValueAsString(user);
时,您实际上是在传递一个代理作为参数。所述代理包含一些映射器无法序列化的属性。
您可以尝试在序列化之前应用过滤器以仅包含您需要的属性:
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider()
.addFilter("myUser", simpleBeanPropertyFilter.filterOutAllExcept("username"));
mapper.setFilters(filterProvider);
return mapper.writeValueAsString(user);
此异常在UnknownSerializer
class中抛出。这是引发异常的确切代码:
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) )");
错误消息附加了无法序列化的 class 的名称。在您的情况下,根据错误消息,问题出在 org.apache.juli.OneLineFormatter
class。所以,MyUser
class是没有问题的。
现在来解释这个错误的原因,它是在序列化一个所有字段都是私有的实体时抛出的。在 org.apache.juli.OneLineFormatter
class 中,所有字段都是私有的,没有任何 public getter 和 setter 方法。
我的用户对象的 Jackson 序列化遇到了问题。 有一些带有 getter 和 setter 的私有字段。当我这样做时一切正常:
public String json() {
MyUser user = new MyUser();
user.setUsername("myName");
return mapper.writeValueAsString(user); // Valid JSON
}
但我想使用 Spring 框架自动装配用户对象:
@Autowired
private MyUser user;
public String json() {
System.out.println(user.getUsername()); // Property set before and it works
return mapper.writeValueAsString(user); // 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$f23855e["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)
当我试图忽略这些未知错误时
mapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
我得到了一个无限递归:
com.fasterxml.jackson.databind.JsonMappingException: Infinite recursion (WhosebugError) (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"]
...
看起来 Spring 对自动装配的 MyUser 实例做了一些错误,因此 Jackson 无法序列化它。
有办法解决吗?
更新
MyUser class 非常简单:
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;
}
}
由于您使用 MyUser
作为 Spring 托管 bean,Spring 将您的对象包装到代理中 - 所以当您调用 mapper.writeValueAsString(user);
时,您实际上是在传递一个代理作为参数。所述代理包含一些映射器无法序列化的属性。
您可以尝试在序列化之前应用过滤器以仅包含您需要的属性:
ObjectMapper mapper = new ObjectMapper();
SimpleFilterProvider simpleFilterProvider = new SimpleFilterProvider()
.addFilter("myUser", simpleBeanPropertyFilter.filterOutAllExcept("username"));
mapper.setFilters(filterProvider);
return mapper.writeValueAsString(user);
此异常在UnknownSerializer
class中抛出。这是引发异常的确切代码:
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) )");
错误消息附加了无法序列化的 class 的名称。在您的情况下,根据错误消息,问题出在 org.apache.juli.OneLineFormatter
class。所以,MyUser
class是没有问题的。
现在来解释这个错误的原因,它是在序列化一个所有字段都是私有的实体时抛出的。在 org.apache.juli.OneLineFormatter
class 中,所有字段都是私有的,没有任何 public getter 和 setter 方法。