问题描述
我正在使用 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
属性。