使用jackson和spring-boot将base64编码的JSON解码为POJO

时间:2017-06-05 14:42:33

标签: java json spring-mvc spring-boot jackson

我有这样的请求

{
    "varA"  : "A",
    "varB" : "TCFNhbiBKb3NlMRgwFgYDVQQK"
}

其中key varB是base64编码的JSON字符串。像这样的东西:

{
    "nestedVarB1": "some value here",
    "nestedVarB2" : "some other value here"
}

我想把它转换成像这样的POJO:

@Data
public class MyRequest {
    private String varA;
    private B varB;
}

@Data
public class B {
    private String nestedVarB1;
    private String nestedVarB2;
}

我在thisthis之类的堆栈溢出上经历了几个解决方案,但是我想将JSON直接转换为MyRequest类型的对象,可能是通过编写某种类型的Jackson解串器

如何使用Jackson和Spring Boot将JSON直接转换为MyRequest

注意:

  1. POJO MyRequestB非常大,B可以进一步嵌套,因此手动执行将是一项艰巨的任务。
  2. 我对来的请求没有任何控制权,它来自第三方来源。因此,无法更改请求的格式。

1 个答案:

答案 0 :(得分:2)

我做了一些实验,这里有一个简单的Jackson Deserializer,应该适合你。

Deserializer实现ContextualDeserializer接口以访问实际的bean属性(例如varB)。检测正确的结果类型是必要的,因为反序列化器本身可以附加到任何类型的字段。

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
            );
        }
    }
}

以下是映射类的示例。

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;
    }
}