问题描述
我有这样的请求
{
"varA" : "A",
"varB" : "TCFNhbiBKb3NlMRgwFgYDVQQK"
}
其中key varB
是一个base64编码的JSON字符串。类似这样的事情:
where key varB
is a base64 encoded JSON string. something like this:
{
"nestedVarB1": "some value here",
"nestedVarB2" : "some other value here"
}
我想把它转换成一些POJO像这个:
I want to convert it into some POJOs like this:
@Data
public class MyRequest {
private String varA;
private B varB;
}
@Data
public class B {
private String nestedVarB1;
private String nestedVarB2;
}
我在堆栈溢出上经历了几个解决方案,如和,但我想将JSON直接转换为 MyRequest
类型的对象写一些杰克逊反序列化器。
I went through several solutions on stack overflow like this and this, but I want to convert the JSON directly into an object of type MyRequest
maybe by writing some sort of Jackson deserializer.
如何使用Jackson和Spring Boot将JSON直接转换为 MyRequest
?
How can I convert the JSON directly into MyRequest
using Jackson and Spring Boot?
注意:
- POJOs
MyRequest
和B
非常大,B
可以进一步嵌套,所以手动执行会很大任务。 - 我对来的请求没有任何控制权,它来自第三方来源。所以,不能改变请求的格式。
- POJOs
MyRequest
andB
are very big andB
could be further nested, so doing it manually would be a big task. - I don't have any control over the request coming, it is coming from a third party source. So, can't change the format of the request.
推荐答案
我做了一些实验,这里是一个简单的杰克逊反序列化器,它应该适合你。
I've done some experiments and here is a simple Jackson Deserializer which should work for you.
反序列化器实现ContextualDeserializer接口以访问实际的bean属性(例如 varB
)。检测正确的结果类型是必要的,因为反序列化器本身可以附加到任何类型的字段。
Deserializer implements the ContextualDeserializer interface to get access to actual bean property (for example varB
). It's necessary for detecting correct result type, because deserializer itself can be attached to a field of any type.
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.*;
import com.fasterxml.jackson.databind.deser.ContextualDeserializer;
import com.fasterxml.jackson.databind.exc.InvalidFormatException;
import java.io.IOException;
import java.util.Base64;
public class Base64Deserializer extends JsonDeserializer<Object> implements ContextualDeserializer {
private Class<?> resultClass;
@Override
public JsonDeserializer<?> createContextual(DeserializationContext context, BeanProperty property) throws JsonMappingException {
this.resultClass = property.getType().getRawClass();
return this;
}
@Override
public Object deserialize(JsonParser parser, DeserializationContext context) throws IOException, JsonProcessingException {
String value = parser.getValueAsString();
Base64.Decoder decoder = Base64.getDecoder();
try {
ObjectMapper objectMapper = new ObjectMapper();
byte[] decodedValue = decoder.decode(value);
return objectMapper.readValue(decodedValue, this.resultClass);
} catch (IllegalArgumentException | JsonParseException e) {
String fieldName = parser.getParsingContext().getCurrentName();
Class<?> wrapperClass = parser.getParsingContext().getCurrentValue().getClass();
throw new InvalidFormatException(
parser,
String.format("Value for '%s' is not a base64 encoded JSON", fieldName),
value,
wrapperClass
);
}
}
}
以下是映射示例类。
Here is an example of mapped class.
public class MyRequest {
private String varA;
@JsonDeserialize(using = Base64Deserializer.class)
private B varB;
public String getVarA() {
return varA;
}
public void setVarA(String varA) {
this.varA = varA;
}
public B getVarB() {
return varB;
}
public void setVarB(B varB) {
this.varB = varB;
}
}
这篇关于使用jackson和spring-boot将base64编码的JSON解码为POJO的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!