Reputation: 1492
I have a request coming like this
{
"varA" : "A",
"varB" : "TCFNhbiBKb3NlMRgwFgYDVQQK"
}
where key varB
is a base64 encoded JSON string. something like this:
{
"nestedVarB1": "some value here",
"nestedVarB2" : "some other value here"
}
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;
}
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.
How can I convert the JSON directly into MyRequest
using Jackson and Spring Boot?
Note:
MyRequest
and B
are very big and B
could be further nested, so doing it manually would be a big task.Upvotes: 4
Views: 14570
Reputation: 381
I've done some experiments and here is a simple Jackson Deserializer which should work for you.
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;
}
}
Upvotes: 6