我有两个班级:
public class ResponseInfo {
private final int code;
private final String description;
@JsonCreator
public static ResponseInfo of(
@JsonProperty("code") int code,
@JsonProperty("description") String description
) {
return new ResponseInfo(code, description);
}
private ResponseInfo(
int code,
String description
) {
this.code = code;
this.description = description;
}
@JsonProperty("code")
public int code() {
return code;
}
@JsonProperty("description")
public String description() {
return description;
}
}
和
public class Response<T> {
private final ResponseInfo responseInfo;
private final T payload;
public static <T> Response<T> of(ResponseInfo responseInfo, T payload) {
return new Response<>(responseInfo, payload);
}
private Response(ResponseInfo responseInfo, T payload) {
this.responseInfo = responseInfo;
this.payload = payload;
}
@JsonUnwrapped
public ResponseInfo responseInfo() {
return responseInfo;
}
@JsonUnwrapped
public T payload() {
return payload;
}
}
我使用它们将其他信息添加到响应中(作为代码和描述)。例如:
Response.of(ResponseInfo.of(0, "OK"), User.of("Oleg", 23))
将序列化为:
{
"age": 23,
"code": 0,
"description": "OK",
"name": "Oleg"
}
如何进行响应的反序列化?
我无法直接在@JsonProperty
中使用@JsonCreator
因为我不知道有效负载的属性。
JsonCreator
@JsonUnwrapped
也不起作用。
我正在使用jackson-datatype-jdk8:2.9.5
。
答案 0 :(得分:0)
我已经创建了实现。
public class ResponseDeserializer
extends JsonDeserializer<Response<?>>
implements ContextualDeserializer {
private JavaType type;
@SuppressWarnings("unused")
public ResponseDeserializer() {
}
private ResponseDeserializer(JavaType type) {
this.type = type;
}
@Override
public JsonDeserializer<?> createContextual(
DeserializationContext context,
BeanProperty beanProperty
) {
JavaType contextualType = context.getContextualType();
if(contextualType == null) {
contextualType = beanProperty.getMember()
.getType();
}
if (!contextualType.isTypeOrSubTypeOf(Response.class)) {
throw new IllegalArgumentException("contextualType should be " + Response.class.getName());
}
final JavaType payloadType = contextualType.containedType(0);
return new ResponseDeserializer(payloadType);
}
@Override
public Response<?> deserialize(
JsonParser jsonParser,
DeserializationContext context
) throws IOException {
final ObjectCodec codec = jsonParser.getCodec();
JsonNode rootNode = codec.readTree(jsonParser);
final ResponseInfo responseInfo = ResponseInfo.of(
rootNode.get("code").asInt(),
rootNode.get("description").asText()
);
final JsonNode payloadNode = createPayloadNode(rootNode, codec);
final JsonParser payloadParser = payloadNode.traverse();
final Object payload = codec.readValue(payloadParser, type);
return Response.of(responseInfo, payload);
}
private JsonNode createPayloadNode(JsonNode rootNode, ObjectCodec codec) {
final Map<String, JsonNode> remainingNodes = findRemainingNodes(rootNode);
if(remainingNodes.size() == 1) {
final JsonNode payloadNode = remainingNodes.get("payload");
if(payloadNode != null && !payloadNode.isObject()) {
return payloadNode;
}
}
return buildRemainingNode(remainingNodes, codec);
}
private JsonNode buildRemainingNode(Map<String, JsonNode> remainingNodes, ObjectCodec codec) {
final ObjectNode remainingNode = (ObjectNode) codec.createObjectNode();
remainingNodes.forEach(remainingNode::set);
return remainingNode;
}
private Map<String, JsonNode> findRemainingNodes(JsonNode rootNode) {
Map<String, JsonNode> remainingNodes = new HashMap<>();
rootNode.fields()
.forEachRemaining(entry -> {
final String key = entry.getKey();
if(key.equals("code") || key.equals("description")) {
return;
}
remainingNodes.put(key, entry.getValue());
});
return remainingNodes;
}
}