В наших весенних проектах данных у нас есть «стандартный» подход к написанию наших DTO, где мы используем ломбок @Value
и @Builder
для неизменности и @JsonDeserialize(builder = SomeClass.SomeClassBuilder.class)
для десериализации Джексона.
Вот минимальный пример:
@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, например:
{
"id": "c29tZWlk",
"clientData": "eyJzb21ldGhpbmciOiJzb21ldGhpbmdWYWx1ZSIsInNvbWV0aGluZ0Vsc2UiOjF9"
}
Было бы замечательно, если бы мы могли прозрачно декодировать и дешифровать Стрифицируйте это поле как часть десериализации PostBody
, прежде чем он вызовет, запускает десериализатор для ClientData
.
. Одним из решений является создание настраиваемого десериализатора для PostBody
, но в реальном примере есть много дополнительные поля, которые затем необходимо обрабатывать вручную.
Я пытался создать собственный десериализатор ClientData, но я изо всех сил пытаюсь понять множество различных типов доступных интерфейсов десериализатора.
Пока у меня есть что-то вроде этого:
@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);
}
}
Буду признателен за любые идеи о том, как продвигаться в этом примере, или какой-то другой механизм, который я могу упустить решить эту проблему?
Ура