【问题标题】:Disable field serialization per ObjectMapper禁用每个 ObjectMapper 的字段序列化
【发布时间】:2021-05-14 08:55:03
【问题描述】:

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

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

public class MyClass {

  @JsonProperty(access = WRITE_ONLY)
  private String field;

  ...

}

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

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

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

【问题讨论】:

  • 您可以尝试使用像@Server 这样的自定义注释并实现这个stackoverflow.com/questions/43342097/… 服务器和客户端之间的共享模块可以有像getServerObjectMapper()getClientObjectMapper() 这样的方法,这将添加这个序列化程序或不是相应的。
  • 感谢您的回答,但我不知道这是否适合我的情况。在示例中,@JsonSerialize(using = UnitSerializer.class) 用于字段。所以它会在运行时自动解析。以编程方式,我只能为每种类型添加序列化程序。另外,如果可能的话,我现在不想介绍共享模块
  • 仅在getter方法上使用@JsonIgnore,在链接link中回答
  • @NasirHussain,它在服务器端工作时。但是,在客户端,当我发送此字段时,杰克逊会忽略它。

标签: java json serialization jackson mixins


【解决方案1】:

当您在两端使用通用模型类时:客户端和服务器,您可以使用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 属性。

【讨论】:

  • 我昨天想通了,现在我看到了你的答案。这与我发现的想法完全相同。无论如何,我离开它以收集更多建议。这个很好地处理了这种情况,所以我将其标记为已解决:)。
猜你喜欢
  • 1970-01-01
  • 2021-12-11
  • 2016-06-29
  • 1970-01-01
  • 1970-01-01
  • 2016-12-29
  • 1970-01-01
  • 2016-06-10
  • 2020-09-04
相关资源
最近更新 更多