Decode base64 encoded JSON to POJO with jackson and spring-boot
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;
}
}
Comments
-
Saheb about 2 years
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:
- 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.
- POJOs
-
Saheb about 7 yearsI noticed that the request coming is in
application/x-www-form-urlencoded
format so I can't use Jackson serializer here. Accepting your answer as it works fine for Application/JSON asked in the question. Can you suggest something if data is comingapplication/x-www-form-urlencoded
? -
Lukáš Kováč about 7 yearsCan you please provide an example of request? Keys "varA", "varB" are on the top level of the request, or they are wrapped?
-
Saheb about 7 yearsyes
varA
andvarB
are top level. Something like thisvarB={base64encoded string here}&varA="some string"
. Also, I have asked a separate question related to this here. -
Lukáš Kováč about 7 yearsjust to clarify, so top level object comes as
x-www-form-urlencoded
, withvarB
which contains base64 encoded JSON, correct? -
kris larson over 2 yearsThis happens for real: developer.android.com/google/play/billing/rtdn-reference so thanks for this answer