禁用每个 ObjectMapper 的字段序列化

问题描述

我正在使用 application/json Content-Type(服务器)开发 REST 应用程序。我也在为它开发 REST 客户端库(客户端)。服务器和客户端都使用相同的 Jackson 注释类/资源。

我的服务器用例之一包括添加一个应为只写的字段(仅启用反序列化)。我是这样做的:

public class MyClass {

  @JsonProperty(access = WRITE_ONLY)
  private String field;

  ...

}

但是,由于这个类也在客户端使用,我无法将值发送到这个字段,因为序列化处理会跳过它。我希望客户端能够序列化这个字段。服务器和客户端使用单独的对象映射器。

我可以使用 JsonSerializer<MyClass> 的单独实现并将其设置为对象映射器,但这意味着我必须手动序列化所有其他字段。我不要这个。

我想知道,是否有某种方法可以指示对象映射器(或向其中注入某些内容)以不同方式处理此类字段?

解决方法

当您在客户端和服务器端使用通用模型类时,您可以使用 com.fasterxml.jackson.databind.Module 类及其实现注册所有差异。如果某些 Jackson 配置应仅在一侧可用,您可以将其移至 MixIn 类/接口并仅在指定一侧注册。

简单例子:

import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.databind.module.SimpleModule;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;

import java.io.IOException;

public class ClientServerApp {

    public static void main(String[] args) throws IOException {
        // Client side
        ObjectMapper clientMapper = JsonMapper.builder().build();

        // create payload on client side
        MyClass instance = new MyClass(1,"fieldValue");
        String payload = clientMapper.writeValueAsString(instance);

        // send to server
        System.out.println("Send: " + payload);
        // ..

        // Server side
        ObjectMapper serverMapper = JsonMapper.builder()
                .addModule(new ServerModule())
                .build();
        MyClass deserialized = serverMapper.readValue(payload,MyClass.class);
        System.out.println("Deserialized: " + deserialized);

        System.out.println("Payload on server side: " + serverMapper.writeValueAsString(deserialized));
    }
}

class ServerModule extends SimpleModule {
    public ServerModule() {
        setMixInAnnotation(MyClass.class,MyClassServerMixIn.class);
        // add other configuration
    }
}

@Data
@AllArgsConstructor
@NoArgsConstructor
class MyClass {

    private int id;
    private String field;
}

interface MyClassServerMixIn {

    @JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
    String getField();
}

以上代码打印:

Send: {"id":1,"field":"fieldValue"}
Deserialized: MyClass(id=1,field=fieldValue)
Payload on server side: {"id":1}

如您所见,只有客户端的 ObjectMapper 可以序列化 field 属性。