序列化 Hibernate 对象时抛出奇怪的 Jackson 异常
杰克逊抛出了一个奇怪的异常,我不知道如何解决。我正在使用 Spring、Hibernate 和 Jackson。
我已经考虑到延迟加载是导致问题的原因,但我已采取措施告诉 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*() 方法。咕噜!!我有什么办法可以告诉杰克逊不要在代理上处理任何内容,或者我是这样吗?这真的很奇怪,因为吐出 JSON 的方法仅在某些情况下崩溃,而不是一直崩溃。尽管如此,这是由于代理对象上的 get*() 方法造成的。
旁白:代理是邪恶的。它们扰乱了 Jackson、equals() 以及常规 Java 编程的许多其他部分。我很想完全放弃 Hibernate :/
Jackson is throwing a weird exception that I don't know how to fix. I'm using Spring, Hibernate and Jackson.
I have already considered that lazy-loading is causing the problem, but I have taken measures to tell Jackson to NOT process various properties as follows:
@JsonIgnoreProperties({ "sentMessages", "receivedMessages", "educationFacility" })
public class Director extends UserAccount implements EducationFacilityUser {
....
}
I have done the same thing for all the other UserAccount subclasses as well.
Here's the exception being thrown:
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)
Suggestions on how I can get more info to see what's causing this? Anyone know how to fix it?
EDIT: I discovered that getHander() and other get*() methods exist on the proxy object. GRR!! Is there any way I can tell Jackson to not process anything on the proxy, or am I sol? This is really weird because the method that spits out the JSON only crashes under certain circumstances, not all the time. Nonetheless, it's due to the get*() methods on the proxy object.
Aside: Proxies are evil. They disrupt Jackson, equals() and many other parts of regular Java programming. I am tempted to ditch Hibernate altogether :/
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(15)
我通过休眠代理对象进行延迟加载时遇到了类似的问题。通过注释具有延迟加载私有属性的类来解决这个问题:
我假设您可以在代理对象上添加属性,从而破坏该注释的 JSON 序列化。
避免在未获取的惰性对象上进行 Jackson 序列化
I had a similar problem with lazy loading via the hibernate proxy object. Got around it by annotating the class having lazyloaded private properties with:
I assume you can add the properties on your proxy object that breaks the JSON serialization to that annotation.
Avoid Jackson serialization on non fetched lazy objects
这并不理想,但您可以在类级别使用
@JsonAutoDetect
禁用 Jackson 对 JSON 属性的自动发现。这将阻止它尝试处理 Javassist 的东西(并且失败)。这意味着您必须手动注释每个 getter(使用 @JsonProperty),但这不一定是坏事,因为它使事情保持明确。
It's not ideal, but you could disable Jackson's auto-discovery of JSON properties, using
@JsonAutoDetect
at the class level. This would prevent it from trying to handle the Javassist stuff (and failing).This means that you then have to annotate each getter manually (with
@JsonProperty
), but that's not necessarily a bad thing, since it keeps things explicit.我遇到了同样的错误,但与 Hibernate 无关。我在这里被所有可怕的建议吓到了,我想这些建议与休眠和延迟加载有关......
然而,就我而言,我收到了错误,因为在内部类中我没有 getter/setter,因此 BeanSerializer 无法序列化数据
...设置器解决了这个问题。
i got the same error, but with no relation to Hibernate. I got scared here from all frightening suggestions, which i guess relevant in case of Hibernate and lazy loading...
However, in my case i got the error since in an inner class i had no getters/setters, so the BeanSerializer could not serialize the data...
Adding getters & setters resolved the problem.
就其价值而言,有一个刚刚启动的 Jackson Hibernate module 项目,它应该可以解决这个问题,并希望解决其他问题以及。
项目与 Jackson 项目相关,尽管不是核心源的一部分。这主要是为了简化发布过程;它将需要 Jackson 1.7,因为那时正在引入 Module API。
For what it's worth, there is Jackson Hibernate module project that just started, and which should solve this problem and hopefully others as well.
Project is related to Jackson project, although not part of core source. This is mostly to allow simpler release process; it will require Jackson 1.7 as that's when Module API is being introduced.
我也有同样的问题。查看您是否使用
hibernatesession.load()
。如果是这样,请尝试转换为hibernatesession.get()
。这解决了我的问题。I had the same problem. See if you are using
hibernatesession.load()
. If so, try converting tohibernatesession.get()
. This solved my problem.与其他答案类似,我的问题是声明一个多对一列来执行延迟获取。切换到急切获取解决了这个问题。
之前:
之后:
Similar to other answers, the problem for me was declaring a many-to-one column to do lazy fetching. Switching to eager fetching fixed the problem.
Before:
After:
我从 spring 的 @RestController 收到了同样的错误消息。我的休息控制器类使用 spring 的 JpaRepository 类,并用
repository.findOne(id) 替换
repository.getOne(id)
方法调用,问题是走了。I had the same error message from spring's
@RestController
. My rest controller class was using spring'sJpaRepository
class and by replacingrepository.getOne(id)
method call withrepository.findOne(id)
problem was gone.您可以使用 jackson-datatype-hibernate 模块来解决这个问题。它对我有用。
参考:https://github.com/FasterXML/jackson-datatype-hibernate
You can use jackson-datatype-hibernate module to solve this problem. It work for me.
reference: https://github.com/FasterXML/jackson-datatype-hibernate
您可以在类“Director”上使用
@JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })
注释You could use
@JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })
annotation on your class "Director"我遇到了同样的问题,致敬在这里
避免在非获取惰性上进行 Jackson 序列化对象
http://blog.pastelstudios.com/2012/03/12/spring-3-1-hibernate-4-jackson-module-hibernate/
https://github.com/nessonqk/jackson-datatype-hibernate
I got the same issue, salutations are here
Avoid Jackson serialization on non fetched lazy objects
http://blog.pastelstudios.com/2012/03/12/spring-3-1-hibernate-4-jackson-module-hibernate/
https://github.com/nessonqk/jackson-datatype-hibernate
您可以在 Object.class 上添加 Jackson mixin 以始终忽略与 hibernate 相关的属性。如果您使用 Spring Boot,请将其放入您的 Application 类中:
You can add a Jackson mixin on Object.class to always ignore hibernate-related properties. If you are using Spring Boot put this in your Application class:
您还可以将您的域对象 Director 设置为最终的。这不是完美的解决方案,但它阻止创建域类的代理子类。
Also you can make your domain object Director final. It is not perfect solution but it prevent creating proxy-subclass of you domain class.
我是 Jackson API 的新手,当我收到“org.codehaus.jackson.map.JsonMappingException:找不到类 com.company.project.yourclass 的序列化器”时,我将 getter 和 setter 添加到 com.company.project.yourclass ,这帮助我使用 ObjectMapper 的映射器对象将 java 对象写入平面文件。
I am New to Jackson API, when i got the "org.codehaus.jackson.map.JsonMappingException: No serializer found for class com.company.project.yourclass" , I added the getter and setter to com.company.project.yourclass, that helped me to use the ObjectMapper's mapper object to write the java object into a flat file.
我遇到了同样的问题,很奇怪的是,相同的代码在少数情况下有效,而在某些随机情况下却失败了。
我通过确保正确的设置器/获取器(确保区分大小写)来修复它
I faced the same issue and It is really strange that the same code works in few case whereas it failed in some random cases.
I got it fixed by just making sure the proper setter/getter (Making sure the case sensitivity)
我尝试了
@JsonDetect
和@JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })
它们都不适合我。对我来说,使用第三方模块似乎需要做很多工作。因此,我只是尝试在传递给 Jackson 进行序列化之前对惰性对象的任何属性进行 get 调用。工作代码片段看起来像这样:
I tried
@JsonDetect
and@JsonIgnoreProperties(value = { "handler", "hibernateLazyInitializer" })
Neither of them worked for me. Using a third-party module seemed like a lot of work to me. So I just tried making a
get
call on any property of the lazy object before passing tojackson
for serlization. The working code snippet looked something like this :