【问题标题】:Jackson's Access.WRITE_ONLY during test null杰克逊在测试期间的 Access.WRITE_ONLY 空
【发布时间】:2018-01-22 14:09:29
【问题描述】:

我目前正在使用 Jackson 的反序列化功能,但遇到了一个问题,我不知道如何解决。

在我的测试过程中,@JsonProperty(access = JsonProperty.Access.WRITE_ONLY) 注释被忽略,它只显示null。 但是,例如邮递员一切正常。

我只使用带有 Web Starter 和 Test Starter 依赖项的 Spring Boot Starter。

示例代码:

@SpringBootApplication
public class DemoApplication {

    public static void main(String[] args) {
        SpringApplication.run(DemoApplication.class, args);
    }
}

@RestController
class JacksonExampleRestController {

    @PostMapping("/api")
    public void getResti(@RequestBody JacksonModel jacksonModel) {
        System.out.println(jacksonModel.getId());
        System.out.println(jacksonModel.getPassword());
    }
}

class JacksonModel {

    private String id;

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    private String password;

    public String getId() {
        return id;
    }

    public void setId(String id) {
        this.id = id;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }
}

测试:

@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoApplicationTests {

    private MockMvc mockMvc;

    @Before
    public void setUp() {

        JacksonExampleRestController jacksonExampleRestController = new JacksonExampleRestController();

        mockMvc = MockMvcBuilders.standaloneSetup(jacksonExampleRestController)
                .build();
    }

    @Test
    public void testJackson() throws Exception {
        JacksonModel jacksonModel = new JacksonModel();
        jacksonModel.setId("id");
        jacksonModel.setPassword("password");

        mockMvc.perform(post("/api").
                contentType(APPLICATION_JSON_UTF8)
                .content(convertObjectToJsonBytes(jacksonModel)));
    }

    public static byte[] convertObjectToJsonBytes(Object object)
            throws IOException {
        ObjectMapper mapper = new ObjectMapper();
        mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
        return mapper.writeValueAsBytes(object);
    }
}

这是默认行为吗?是我必须在测试中配置一些东西还是我现在看不到的其他东西?

【问题讨论】:

  • 在不运行代码的情况下,我的第一反应是查看您使用 Jackson 使用被测对象生成 JSON 字节的事实。可能会打印出convertObjectToJsonBytes 返回的值并检查json字符串是否正常?
  • 在检查方法时,它只返回 Id。所以我添加了mapper.configure(MapperFeature.USE_ANNOTATIONS, false); 并且它有效......这干净吗?因为感觉不对……
  • 我会继续使用 HashMap 来生成 JSON。因此,如果您考虑一下,您正在测试的是端点。访问此端点的人不会使用您的模型对象,那么为什么要在测试中使用它们呢?我知道这很方便,但不使用相同的对象来生成请求可能更安全。

标签: java rest testing spring-boot jackson


【解决方案1】:

为您的 ObjectMapper 添加该行:

mapper.disable(MapperFeature.USE_ANNOTATIONS);

【讨论】:

    【解决方案2】:

    忽略所有注释可能会有问题。要处理更精细的配置,您可以实现自定义 JacksonAnnotationIntrospector

    public class IgnoreJacksonWriteOnlyAccess extends JacksonAnnotationIntrospector {
    
        @Override
        public JsonProperty.Access findPropertyAccess(Annotated m) {
            JsonProperty.Access access = super.findPropertyAccess(m);
            if (access == JsonProperty.Access.WRITE_ONLY) {
                return JsonProperty.Access.AUTO;
            }
            return access;
        }
    }
    

    然后,在实例化映射器之后:

    mapper.setAnnotationIntrospector(new IgnoreJacksonWriteOnlyAccess());
    

    【讨论】:

      【解决方案3】:

      我遇到了同样的问题,设置类似。问题出在测试输入数据中。基本上,writeValueAsBytes() 将完全按照注释的指示序列化时忽略密码。

      请注意,Access.WRITE_ONLY 基本上表示“SetterOnly”或“DeserializationOnly”,而不是相反。

      【讨论】:

        猜你喜欢
        • 2012-03-14
        • 2012-11-07
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2022-06-22
        • 1970-01-01
        • 2021-01-03
        • 1970-01-01
        相关资源
        最近更新 更多