Java 解码和反序列化字段的最简单方法,该字段的值是带Jackson的base64编码、字符串化JSON blob
在spring数据项目中,我们使用“标准”方法编写DTO,其中使用lombok的Java 解码和反序列化字段的最简单方法,该字段的值是带Jackson的base64编码、字符串化JSON blob,java,spring-boot,jackson,json-deserialization,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)
@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"
}
如果我们能够在PostBody
调用之前透明地解码和反序列化此字段,并在其运行ClientData
的反序列化程序,这将是一件非常棒的事情
一种解决方案是为PostBody
创建自定义反序列化程序,但在一个实际示例中,还有很多字段需要手动处理
我曾尝试创建自定义ClientData反序列化程序,但我很难理解各种不同类型的desrializer接口
到目前为止,我得到了类似的信息:
@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);
}
}
@Value
@建筑商
@JsonDeserialize(builder=PostBody.PostBodyBuilder.class)
类PostBody{
字节[]id;
@JsonDeserialize(使用=clientDatabase64反序列化器.class)
ClientData ClientData;
@JsonPOJOBuilder(前缀为“”)
公共静态类PostBodyBuilder{}
}
//剪断
类ClientDatabase64反序列化程序扩展StdScalarDeserializer{
受保护的ClientDatabase64反序列化程序(){
super(ClientData.class);
}
@凌驾
公共ClientData反序列化(JsonParser、JsonParser、反序列化上下文、反序列化上下文)引发IOException、JsonProcessingException{
byte[]value=Base64.getDecoder().decode(jsonParser.getText());
System.out.println(新字符串(值));//打印字符串化的JSON
setCurrentValue(/*以某种方式将字符串化的JSON转换为树节点?*/value);
返回反序列化context.readValue(jsonParser,ClientData.class);
}
}
如果您有任何关于如何使用这个示例的想法,或者我可能缺少的解决这个问题的其他机制,我将不胜感激
干杯在我提出问题的几分钟后,我终于解决了问题 ClientDatabase64反序列化器和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);
}
}
@Value
@建筑商
@JsonDeserialize(builder=PostBody.PostBodyBuilder.class)
公营邮政机构{
字节[]id;
ClientData ClientData;
公共界面IPostBodyBuilder{
@JsonDeserialize(使用=clientDatabase64反序列化器.class)
PostBody.PostBodyBuilder客户端数据(clientData客户端数据);
}
@JsonPOJOBuilder(前缀为“”)
公共静态类PostBodyBuilder实现IPostBodyBuilder{}
}
类ClientDatabase64反序列化程序扩展StdScalarDeserializer{
私有最终ObjectMapper ObjectMapper;
受保护的ClientDatabase64反序列化程序(ObjectMapper ObjectMapper){
super(ClientData.class);
this.objectMapper=objectMapper;
}
@凌驾
公共客户端数据反序列化(
JsonParser JsonParser,反序列化上下文反序列化上下文
) {
byte[]value=jsonParser.readValueAs(byte[].class);
返回objectMapper.readValue(值,ClientData.class);
}
}
以一种真实的方式,我在提出问题几分钟后就设法解决了问题
ClientDatabase64反序列化器和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);
}
}
@Value
@建筑商
@JsonDeserialize(builder=PostBody.PostBodyBuilder.class)
公营邮政机构{
字节[]id;
ClientData ClientData;
公共界面IPostBodyBuilder{
@JsonDeserialize(使用=clientDatabase64反序列化器.class)
PostBody.PostBodyBuilder客户端数据(clientData客户端数据);
}
@JsonPOJOBuilder(前缀为“”)
公共静态类PostBodyBuilder实现IPostBodyBuilder{}
}
类ClientDatabase64反序列化程序扩展StdScalarDeserializer{
私有最终ObjectMapper ObjectMapper;
受保护的ClientDatabase64反序列化程序(ObjectMapper ObjectMapper){
super(ClientData.class);
this.objectMapper=objectMapper;
}
@凌驾
公共客户端数据反序列化(
JsonParser JsonParser,反序列化上下文反序列化上下文
) {
byte[]value=jsonParser.readValueAs(byte[].class);
返回objectMapper.readValue(值,ClientData.class);
}
}