使用Jackson(JSON)进行序列化-是否获得“找不到序列化程序”?


262

当尝试使用Jackson序列化一个非常简单的对象时,出现异常。错误:

org.codehaus.jackson.map.JsonMappingException:未找到类MyPackage.TestA的序列化程序,也未找到创建BeanSerializer的属性(为避免异常,请禁用SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS))

以下是要序列化的简单类和代码。

谁能告诉我为什么我会收到此错误?

public class TestA {
    String SomeString = "asd";
}

TestA testA = new TestA();
ObjectMapper om = new ObjectMapper();
try {
    String testAString = om.writeValueAsString(testA); // error here!

    TestA newTestA = om.readValue(testAString, TestA.class);
} catch (JsonGenerationException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (JsonMappingException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
} catch (IOException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
}

我写了一篇有关如何用Jackson编写自定义序列化程序的文章,这可能对某些人有帮助。
山姆·贝里

Answers:


329

如前所述,ObjectMapper实例的默认配置是仅访问属于公共字段或具有公共获取器/设置器的属性。更改类定义以使字段公开或提供公共获取者/设置者的另一种方法是(向底层VisibilityChecker)指定不同的属性可见性规则。Jackson 1.9提供了ObjectMapper.setVisibility()方便的方法。对于原始问题中的示例,我可能会将其配置为

myObjectMapper.setVisibility(JsonMethod.FIELD, Visibility.ANY);

对于Jackson> 2.0:

myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);

有关相关配置选项的更多信息和详细信息,建议查看上的JavaDocsObjectMapper.setVisibility()


59
这对我有用。从Jackson 2.0开始,ObjectMapper#setVisibility将PropertyAccessor作为第一个参数。等效的oneliner是 myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
Dan Robinson

@DanRobinson我使用相同的。但是实际上我正在生成yaml文件。所以对于JSONString as:{"term":{"call_failed":"true"}}它正在生成yaml结构,因为:filter: map: term: map: call_failed: "true"为什么要生成map关键字?如何将其删除?
Manish Kumar'8

7
我可能花了8个小时来解决这个错误,但没有意识到我的getter方法上没有“公开”内容。.so愚蠢
Mike Kellogg

1
我在使用对象映射器将ClientResponse转换为字符串时遇到此错误
VdeX

1
您也可以在@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)课程上方添加注释
-veben

74

为了让Jackson对该类进行序列化,SomeString字段必须为public(现在是程序包级别隔离),或者您需要为其定义getter和setter方法。


5
请注意,此答案不正确-该字段无需公开或具有getter和setter。在此问题的另一个答案中,我提供了一种备用配置,该配置不需要更改原始数据结构(将其序列化)。
程序员布鲁斯

9
答案是有用的,即使不是100%完全正确。我忘了在我的var上加上“ public”,这一点已指出。谢谢!
ChrisPhoenix

53

我的源代码中有同样的问题。我刚加

吸气剂

二传手

问题解决了。


1
尝试了许多不同的方法,解决方案就这样简单……。它说得很清楚:“没有发现要创建的属性”。
aks

2
@PhilipRego他的意思是他为该领域添加了一种吸气剂和吸气剂。
保罗

我使用lombok库,因此只添加了批注Getter和Setter。一切都很好。谢谢。
Rahmat Hidayat

是的,getter和setter用于Jackson序列化
。/反

25

在我的情况下,问题是Jackson试图序列化没有属性或方法的空对象。

如异常中所建议的那样,我添加了以下行,以避免在空bean上失败:

对于杰克逊1.9

myObjectMapper.configure(SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS, false);

对于Jackson 2.X

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

您可以找到有关杰克逊禁用fail_on_empty_beans的简单示例


9

对于我拥有控制权的子类,我遇到了同样的问题,对象映射器位于一个通用模块中并且无法访问。我通过为要序列化其对象的子类添加此批注来解决此问题。

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

7

如果您可以编辑包含该对象的类,则通常只需添加注释

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;

2
当您的类具有以get开头的名称的方法时,也会引发此错误。例如NonSerializableClass getMyNonSerializableObject()。杰克逊试图序列化它,但失败了。要解决此问题,只需添加@JsonIgnore或重命名该方法。
Alexey Podlasov

1
使用了旧版本:org.codehaus.jackson.annotate.JsonIgnore
AlikElzin-kilaka,2016年

6

如果您忘记将.build()方法添加到返回状态,也会引发此错误。

return Response.status(Status.OK);         // fails
return Response.status(Status.OK).build(); // works

没有build()方法,出现以下错误:

org.codehaus.jackson.map.JsonMappingException: No serializer found for class com.sun.jersey.core.spi.factory.ResponseBuilderImpl

4

SpringBoot2.0,我通过以下代码解决它:

@Bean public ObjectMapper objectMapper() {
 return new ObjectMapper().disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);}

1
您应该保持模型具有getter和setter方法。
Janus

1
欢迎来到SO!感谢您的贡献。请在您的答案中添加解释,以便清楚了解代码的功能,工作原理以及如何回答OP问题。
Max Vollmer

这对我有帮助!但是我认为,您应该注入上下文的ObjectMapper并在之后进行配置,而不是创建一个新的。
RoBeaToZ

3

对于Oracle Java应用程序,请在ObjectMapper实例化之后添加:

mapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);

2

我在通过休眠代理对象进行延迟加载时遇到了类似的问题。通过用以下方式注释具有延迟加载的私有属性的类来解决此问题:

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

这解决了我的问题。你能告诉我这到底是什么吗?
scarface

2

问题可能是因为您已将变量声明为private。如果您将其更改为public,它将起作用。

更好的选择是使用getter和setter方法。

这样可以解决问题!


2

我发现至少有三种方法可以做到这一点:

  1. 添加public getters您要序列化的实体;
  2. 如果您不想在实体的顶部添加注释public getters。这会将Jackson的默认设置从更改Visbility=DEFAULT@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)那里的任何访问修饰符被接受的。
  3. ObjectMapper通过设置全局更改objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY);。如果您不需要全局此功能,则应避免这种情况。

根据您的需求进行选择。



1

请在bean的类级别使用此:

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

1

添加setter和getter也可以解决我所解决的问题。例如:

public class TestA {
    String SomeString = "asd";

    public String getSomeString () {        return SomeString ;     }

    public void setSomeString (String SS ) {        SomeString = SS ;   } 
}


0

尽管我添加了getter和setter,但我遇到了同样的错误。后来我发现了一个错误,这是在Sonar的建议下,我将吸气剂和吸气剂视为受保护的,从而导致了问题。一旦我修复它,它就会按预期运行。


0

在春季靴2.2.5

添加getter和setter后

我在该字段的顶部添加了@JsonIgnore。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.