java - 使用 Jackson 解码和反序列化其值为 Base64 编码、字符串化 JSON blob 的字段的最简单方法

标签 java spring-boot jackson json-deserialization

在我们的 Spring 数据项目中,我们使用“标准”方法来编写 DTO,其中我们使用 lombok 的 @Value@Builder 来实现不变性,并使用 @JsonDeserialize(builder = SomeClass.SomeClassBuilder.class) 来实现 jackson 反序列化。

这是一个最小的例子:

@RestController
class Controller {
    @PostMapping("/post")
    void post(@RequestBody PostBody body) {
        System.out.println(body);
    }
}

@Value
@Builder
@JsonDeserialize(builder = PostBody.PostBodyBuilder.class)
class PostBody {

    byte[] id;

    ClientData clientData;

    @JsonPOJOBuilder(withPrefix = "")
    public static class PostBodyBuilder {}
}

@Value
@Builder
@JsonDeserialize(builder = ClientData.ClientDataBuilder.class)
class ClientData {
    String something;
    Integer somethingElse;


    @JsonPOJOBuilder(withPrefix = "")
    public static class ClientDataBuilder {}
}

正如您所期望的那样,使用普通的 JSON 负载即可正常工作,例如:

{
  "id": "c29tZWlk",
  "clientData": {
    "something": "somethingValue",
    "somethingElse": 1
  }
}

但是,我们有一个用例,其中 clientData 结构已知,但由于原因,它作为 Base64 编码的字符串化 JSON blob 发送,例如:

{
  "id": "c29tZWlk",
  "clientData": "eyJzb21ldGhpbmciOiJzb21ldGhpbmdWYWx1ZSIsInNvbWV0aGluZ0Vsc2UiOjF9"
}

如果我们能够在调用运行 ClientData 的反序列化器之前,作为 PostBody 反序列化的一部分,透明地解码和反字符串化该字段,那就太好了。

一种解决方案是为 PostBody 创建一个自定义反序列化器,但在实际示例中,还有更多字段需要手动处理。

我尝试创建自定义 ClientData 反序列化器,但我很难理解可用的各种不同类型的反序列化器接口(interface)。

到目前为止我已经得到了这样的东西:

@Value
@Builder
@JsonDeserialize(builder = PostBody.PostBodyBuilder.class)
class PostBody {

    byte[] id;

    @JsonDeserialize(using = ClientDataBase64Deserializer.class)
    ClientData clientData;

    @JsonPOJOBuilder(withPrefix = "")
    public static class PostBodyBuilder {}
}

// SNIP

class ClientDataBase64Deserializer extends StdScalarDeserializer<ClientData> {

    protected ClientDataBase64Deserializer() {
        super(ClientData.class);
    }

    @Override
    public ClientData deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException, JsonProcessingException {
        byte[] value = Base64.getDecoder().decode(jsonParser.getText());
        System.out.println(new String(value)); // prints stringified JSON
        jsonParser.setCurrentValue(/* somehow convert stringified JSON to a Tree Node? */ value);
        return deserializationContext.readValue(jsonParser, ClientData.class);
    }
}

如果您有任何有关如何继续此示例的想法,或者我可能缺少解决此问题的其他机制,我将不胜感激?

干杯

最佳答案

以真正的方式,我在提出问题后几分钟就设法解决了我的问题。

ClientDataBase64Deserializer 和 PostBody 的实现按预期工作:

@Value
@Builder
@JsonDeserialize(builder = PostBody.PostBodyBuilder.class)
public class PostBody {

    byte[] id;

    ClientData clientData;

    public interface IPostBodyBuilder {
        @JsonDeserialize(using = ClientDataBase64Deserializer.class)
        PostBody.PostBodyBuilder clientData(ClientData clientData);
    }

    @JsonPOJOBuilder(withPrefix = "")
    public static class PostBodyBuilder implements IPostBodyBuilder {}
}


class ClientDataBase64Deserializer extends StdScalarDeserializer<ClientData> {
    private final ObjectMapper objectMapper;

    protected ClientDataBase64Deserializer(ObjectMapper objectMapper) {
        super(ClientData.class);
        this.objectMapper = objectMapper;
    }

    @Override
    public ClientData deserialize(
            JsonParser jsonParser, DeserializationContext deserializationContext
    ) {
        byte[] value = jsonParser.readValueAs(byte[].class);
        return objectMapper.readValue(value, ClientData.class);
    }
}

关于java - 使用 Jackson 解码和反序列化其值为 Base64 编码、字符串化 JSON blob 的字段的最简单方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59645093/

相关文章:

spring - 如何编写一个 RestController 从 XML 请求更新 JPA 实体,Spring Data JPA 方式?

java - 子类的 Jackson 序列化

java - JSON对象映射器: avoid listing derived class in serialized JSON string

java - 无法获取 org.hibernate.persister.entity.SingleTableEntityPersister 错误的构造函数

java - 从命令行传递 -r javascript 后如何使 After Effects 退出

java - Spring Boot JPA 使用查询填充实体字段

Spring 应用程序 Jenkins 部署 - 环境

java - Jackson 解析器到 Java 对象

Java - 包含整数列表的 TreeSet?

java - 如何在 Jenkins 中配置 Java 的 Checkstyle 配置