Jackson – JsonMappingException (No serializer found for class) – Jackson – JsonMappingException (No serializer found for class)

最后修改: 2013年 12月 25日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this quick tutorial, we will analyze the marshalling of entities with no getters and the solution for the Jackson JsonMappingException exception.

在这个快速教程中,我们将分析没有getters的实体的marshalling和杰克逊JsonMappingException异常的解决方案

If you want to dig deeper and learn other cool things you can do with the Jackson 2 – head on over to the main Jackson tutorial.

如果你想深入了解并学习你可以用杰克逊2做的其他很酷的事情–请到杰克逊主教程

2. The Problem

2.问题

By default, Jackson 2 will only work with with fields that are either public, or have a public getter methods – serializing an entity that has all fields private or package private will fail:

默认情况下,Jackson 2只适用于公开的字段,或者有公开的getter方法的字段–序列化一个所有字段都是私有的或包私有的实体将失败

public class MyDtoNoAccessors {
    String stringValue;
    int intValue;
    boolean booleanValue;

    public MyDtoNoAccessors() {
        super();
    }

    // no getters
}
@Test(expected = JsonMappingException.class)
public void givenObjectHasNoAccessors_whenSerializing_thenException() 
  throws JsonParseException, IOException {
    String dtoAsString = new ObjectMapper().writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, notNullValue());
}

The full exception is:

完全例外的是。

com.fasterxml.jackson.databind.JsonMappingException: 
No serializer found for class dtos.MyDtoNoAccessors 
and no properties discovered to create BeanSerializer 
(to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) )

3. The Solution

3.解决方案

The obvious solution is to add getters for the fields – if the entity is under our control. If that is not the case and modifying the source of the entity is not possible – then Jackson provides us with a few alternatives.

明显的解决方案是为字段添加获取器–如果实体在我们的控制之下。如果不是这种情况,并且修改实体的来源是不可能的–那么Jackson为我们提供了一些选择。

3.1. Globally Auto Detect Fields With Any Visibility

3.1.全局性地自动检测具有任何可见性的字段

A first solution to this problem is to globally configure the ObjectMapper to detect all fields, regardless of their visibility:

这个问题的第一个解决方案是全局配置ObjectMapper,以检测所有字段,无论它们的可见性如何。

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

This will allow the private and package private fields to be detected without getters, and serialization will work correctly:

这将允许在没有getters的情况下检测到private和package private字段,并且序列化将正确工作。

@Test
public void givenObjectHasNoAccessors_whenSerializingWithAllFieldsDetected_thenNoException() 
  throws JsonParseException, IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.setVisibility(PropertyAccessor.FIELD, Visibility.ANY);
    String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, containsString("intValue"));
    assertThat(dtoAsString, containsString("stringValue"));
    assertThat(dtoAsString, containsString("booleanValue"));
}

3.2. Detected All Fields at the Class Level

3.2.探测到班级层面上的所有字段

Another option Jackson 2 provides is – instead of the global configuration – control the field visibility at the class level via the @JsonAutoDetect annotation:

Jackson 2提供的另一个选项是–代替全局配置–通过@JsonAutoDetect注解在类级别控制字段的可见性

@JsonAutoDetect(fieldVisibility = Visibility.ANY)
public class MyDtoNoAccessors { ... }

With this annotation, the serialization should now work correctly with this particular class:

有了这个注解,现在序列化应该可以在这个特定的类中正确工作。

@Test
public void givenObjectHasNoAccessorsButHasVisibleFields_whenSerializing_thenNoException() 
  throws JsonParseException, IOException {
    ObjectMapper objectMapper = new ObjectMapper();
    String dtoAsString = objectMapper.writeValueAsString(new MyDtoNoAccessors());

    assertThat(dtoAsString, containsString("intValue"));
    assertThat(dtoAsString, containsString("stringValue"));
    assertThat(dtoAsString, containsString("booleanValue"));
}

4. Conclusion

4.结论

This article illustrated how to get around the default field visibility in Jackson, by configuring a custom visibility either globally on the ObjectMapper or on individual classes. Jackson allows even further customization by providing options to control exactly how getters, setters or fields with specific visibilities are seen by the mapper.

本文说明了如何通过在ObjectMapper或单个类上全局配置自定义可见性来绕过Jackson中的默认字段可见性。Jackson通过提供选项来控制映射器如何看到具有特定可见性的getters、setters或字段,从而允许进一步定制。

The implementation of all these examples and code snippets can be found in my GitHub project – this is an Eclipse-based project, so it should be easy to import and run as it is.

所有这些例子和代码片段的实现可以在我的GitHub项目中找到 – 这是一个基于Eclipse的项目,所以应该很容易导入并按原样运行。