使用Jackson(JSON)进行序列化时出现“找不到序列化程序”?

366

当尝试使用Jackson序列化一个非常简单的对象时,我遇到了异常。 错误信息如下:

org.codehaus.jackson.map.JsonMappingException: No serializer found for class MyPackage.TestA and no properties discovered to create BeanSerializer (to avoid exception, disable 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();
}

1
我写了一篇关于如何使用Jackson编写自定义序列化器的文章,对某些人可能会有所帮助。 - Sam Berry
24个回答

442

正如已经描述的那样,ObjectMapper 实例的默认配置是只访问具有公共字段或公共 getter/setter 方法的属性。若要避免更改类定义使字段公开或提供公共 getter/setter 方法,一种替代方法是指定一个不同的属性可见性规则(给底层的 VisibilityChecker)。Jackson 1.9 提供了 ObjectMapper.setVisibility() 方便方法来实现此功能。对于原始问题中的示例,我可能会将其配置为:

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

Jackson版本大于2.0:

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

我建议您查看关于ObjectMapper.setVisibility()的Java文档,以获取更多信息和相关配置选项的详细信息。


61
这对我很有用。从Jackson 2.0开始,ObjectMapper#setVisibility方法的第一个参数是PropertyAccessor。相应的一行代码是myObjectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY); - Dan Robinson
@DanRobinson 我也是用的同样的方法。但实际上我正在生成yaml文件。所以对于JSONString,如:{"term":{"call_failed":"true"}},它会生成以下yaml结构:filter: map: term: map: call_failed: "true"为什么会生成map关键字?我该如何去掉它? - Manish Kumar
9
我可能花了8个小时来纠正这个错误,一直没有意识到我的getter方法上没有加上"public"...太愚蠢了。 - Mike Kellogg
1
当我使用对象映射器将ClientResponse转换为字符串时,我遇到了这个错误。 - VedantK
6
你可以在你的类上方添加注解 @JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY),以实现字段可见性的自动检测。 - veben

146

增加一个

获取器

和一个

设置器

问题就解决了。


4
尝试了许多不同的方法,而解决方案却如此简单......它非常清楚地表明:"未发现要创建的属性"。 - aks
3
他的意思是他为这个字段添加了getter和setter方法。 - Paul
2
我使用lombok库,所以我只需要添加Getter和Setter注解。一切都很好。谢谢。 - Rahmat Hidayat
2
是的,getter和setter用于Jackson序列化/反序列化。 - Ikhiloya Imokhai
4
仅添加getter就解决了我的问题,无需添加setter。 - ddc
显示剩余3条评论

92

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


5
请注意,这个答案是不正确的--这个字段不需要是公共的或者有getter和setter。在对这个问题的另一个回答中,我提供了一种替代的配置方法,它不需要对原始数据结构进行更改就能进行序列化和反序列化。 - Programmer Bruce
10
答案虽然没有100%准确,但仍然有用。我忘记在我的变量上加上“public”,这点被指出来了。谢谢! - ChrisPhoenix

40

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

如异常建议,我添加了以下代码以避免空bean导致失败:

对于Jackson 1.9

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

Jackson 2.X版本

myObjectMapper.configure(SerializationFeature.FAIL_ON_EMPTY_BEANS, false);

您可以在jackson disable fail_on_empty_beans上找到一个简单的示例。


10

我在一个自己掌控的子类中遇到了同样的问题,对象映射器在一个公共模块中并且无法访问。我通过为需要序列化的子类添加此注释来解决问题。

@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY)

9

Jackson使用getter和setter进行序列化/反序列化。因此,在您的模型类中添加getter和setter。


8

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

import com.fasterxml.jackson.annotation.JsonIgnore;

@JsonIgnore 
NonSerializeableClass obj;

2
当你的类有一个以get开头的方法时,也会触发此错误...例如NonSerializableClass getMyNonSerializableObject()。Jackson试图对其进行序列化并失败。要解决此问题,只需添加@JsonIgnore或重命名该方法即可。 - Alexey Podlasov
1
使用旧版本:org.codehaus.jackson.annotate.JsonIgnore - AlikElzin-kilaka

8
如果你忘记在返回状态上添加 .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

7

SpringBoot2.0,我用以下代码解决了它:

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

1
你应该为你的模型添加getter和setter方法。 - Janus
2
欢迎来到SO!感谢您的贡献。请为您的答案添加解释,以便清楚地说明代码的作用、原理和如何回答OP的问题。 - Max Vollmer
这对我有帮助!但是我认为,你应该注入上下文的ObjectMapper并在之后进行配置,而不是创建一个新的ObjectMapper。 - RoBeaToZ

5
我至少发现了三种方法来实现这个:
  1. 在您要序列化的实体上添加 public getters
  2. 如果您不想使用 public getters,则在实体顶部添加注释。这将更改Jackson的默认设置,从Visbility=DEFAULT变为@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY),其中接受任何访问修饰符;
  3. 通过设置 objectMapperInstance.setVisibility(JsonMethod.FIELD, Visibility.ANY); 全局更改您的 ObjectMapper。如果您不需要全局功能,则应避免使用此选项。
根据您的需求进行选择。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接