序列化Hibernate对象时抛出奇怪的Jackson异常

时间:2010-12-05 23:57:10

标签: java json hibernate spring-mvc jackson

杰克逊抛出一个奇怪的例外,我不知道如何解决。我正在使用Spring,Hibernate和Jackson。

我已经考虑过延迟加载会导致问题,但我已采取措施告诉杰克逊不要按如下方式处理各种属性:

@JsonIgnoreProperties({ "sentMessages", "receivedMessages", "educationFacility" })
public class Director extends UserAccount implements EducationFacilityUser {
   ....
}

我也为所有其他UserAccount子类做了同样的事情。

这是抛出的异常:

org.codehaus.jackson.map.JsonMappingException: No serializer found for class org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: java.util.ArrayList[46]->jobprep.domain.educationfacility.Director_$$_javassist_2["handler"])
    at org.codehaus.jackson.map.ser.StdSerializerProvider$1.serialize(StdSerializerProvider.java:62)
    at org.codehaus.jackson.map.ser.BeanPropertyWriter.serializeAsField(BeanPropertyWriter.java:268)
    at org.codehaus.jackson.map.ser.BeanSerializer.serializeFields(BeanSerializer.java:146)
    at org.codehaus.jackson.map.ser.BeanSerializer.serialize(BeanSerializer.java:118)
    at org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:236)
    at org.codehaus.jackson.map.ser.ContainerSerializers$IndexedListSerializer.serializeContents(ContainerSerializers.java:189)
    at org.codehaus.jackson.map.ser.ContainerSerializers$AsArraySerializer.serialize(ContainerSerializers.java:111)
    at org.codehaus.jackson.map.ser.StdSerializerProvider._serializeValue(StdSerializerProvider.java:296)
    at org.codehaus.jackson.map.ser.StdSerializerProvider.serializeValue(StdSerializerProvider.java:224)
    at org.codehaus.jackson.map.ObjectMapper.writeValue(ObjectMapper.java:925)
    at org.springframework.http.converter.json.MappingJacksonHttpMessageConverter.writeInternal(MappingJacksonHttpMessageConverter.java:153)

有关如何获取更多信息以查看导致此问题的建议?任何人都知道如何解决它?

编辑:我发现代理对象上存在getHander()和其他get *()方法。 GRR!有什么办法我可以告诉杰克逊不要在代理上处理任何事情,或者我是谁?这真的很奇怪,因为吐出JSON的方法只会在某些情况下崩溃,而不是一直崩溃。尽管如此,这是由于代理对象上的get *()方法。

除此之外:代理是邪恶的。它们破坏了Jackson,equals()和常规Java编程的许多其他部分。我很想完全放弃Hibernate:/

15 个答案:

答案 0 :(得分:69)

我在通过hibernate代理对象进行延迟加载时遇到了类似的问题。通过使用以下命令注释具有lazyloaded私有属性的类来解决它:

@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})

我假设您可以在代理对象上添加将JSON序列化分解为该批注的属性。

Avoid Jackson serialization on non fetched lazy objects

答案 1 :(得分:38)

这并不理想,但您可以在班级使用@JsonAutoDetect禁用Jackson自动发现的JSON属性。这可以防止它试图处理Javassist的东西(并且失败)。

这意味着您必须手动注释每个getter(使用@JsonProperty),但这不一定是坏事,因为它可以使事情明确。

答案 2 :(得分:23)

我得到了同样的错误,但与Hibernate无关。我从所有可怕的建议中得到了惊吓,我认为在Hibernate和延迟加载的情况下相关...... 但是,在我的情况下我得到了错误,因为在内部类中我没有getter / setter,所以BeanSerializer无法序列化数据......

添加吸气剂&塞特斯解决了这个问题。

答案 3 :(得分:9)

对于它的价值,有Jackson Hibernate module项目刚刚开始,哪个应该解决这个问题,希望其他人也是如此。 项目与杰克逊项目有关,虽然不是核心资源的一部分。这主要是为了让发布过程更简单;当模块API被引入时,它将需要Jackson 1.7。

答案 4 :(得分:6)

我遇到了同样的问题。看看您是否使用hibernatesession.load()。如果是,请尝试转换为hibernatesession.get()。这解决了我的问题。

答案 5 :(得分:5)

我从spring @RestController收到了同样的错误消息。我的其他控制器类使用的是spring JpaRepository类,并且用repository.getOne(id)替换repository.findOne(id)方法调用问题已经消失。

答案 6 :(得分:4)

您可以使用jackson-datatype-hibernate模块来解决此问题。它对我有用。 参考:https://github.com/FasterXML/jackson-datatype-hibernate

答案 7 :(得分:3)

答案 8 :(得分:3)

与其他答案类似,我的问题是声明多对一列进行延迟抓取。切换到急切提取修复了问题。 之前:

@ManyToOne(targetEntity = StatusCode.class, fetch = FetchType.LAZY)

后:

@ManyToOne(targetEntity = StatusCode.class, fetch = FetchType.EAGER)

答案 9 :(得分:2)

您可以在班级“导演”上使用@JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })注释

答案 10 :(得分:2)

您可以在Object.class上添加Jackson mixin以始终忽略与hibernate相关的属性。如果您使用的是Spring Boot,请将其放在Application类中:

@Bean
public Jackson2ObjectMapperBuilder jacksonBuilder() {
    Jackson2ObjectMapperBuilder b = new Jackson2ObjectMapperBuilder();
    b.mixIn(Object.class, IgnoreHibernatePropertiesInJackson.class);
    return b;
}


@JsonIgnoreProperties({"hibernateLazyInitializer", "handler"})
private abstract class IgnoreHibernatePropertiesInJackson{ }

答案 11 :(得分:0)

我是Jackson API的新手,当我收到“org.codehaus.jackson.map.JsonMappingException:没有找到类com.company.project.yourclass的序列化程序”时,我将getter和setter添加到了com.company。 project.yourclass,帮助我使用ObjectMapper的mapper对象将java对象写入平面文件。

答案 12 :(得分:0)

我遇到了同样的问题,同样的代码在少数情况下工作,而在某些随机情况下失败,这真的很奇怪。

我通过确保正确的setter / getter(确保区分大小写)来解决问题

答案 13 :(得分:0)

我尝试了@JsonDetect

@JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })

他们都没有为我工作。使用第三方模块对我来说似乎很多工作。所以我只是尝试对惰性对象的任何属性进行get调用,然后传递给jackson进行serlization。工作代码段看起来像这样:

@RequestMapping(value = "/authenticate", produces = "application/json; charset=utf-8")
    @ResponseBody
    @Transactional
    public Account authenticate(Principal principal) {
        UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = (UsernamePasswordAuthenticationToken) principal;
        LoggedInUserDetails loggedInUserDetails = (LoggedInUserDetails) usernamePasswordAuthenticationToken.getPrincipal();
        User user = userRepository.findOne(loggedInUserDetails.getUserId());
        Account account = user.getAccount();
        account.getFullName();      //Since, account is lazy giving it directly to jackson for serlization didn't worked & hence, this quick-fix.
        return account;
    }

答案 14 :(得分:0)

此外,您可以将您的域对象Director设为最终版。它不是完美的解决方案,但它会阻止您创建域类的代理子类。