2 回答

TA貢獻1831條經驗 獲得超9個贊
我認為要解決這個問題,您需要一個用于類Notification中字段的自定義反序列化器MessageWrapper以及一個用于類Mail中字段的自定義反序列化器Notification,如下所示:
public class NotificationDeserializer extends JsonDeserializer<Notification> {
@Override
public Notification deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String text = p.getText();
return new ObjectMapper().readValue(text, Notification.class);
}
}
public class MailDeserializer extends JsonDeserializer<Mail> {
@Override
public Mail deserialize(JsonParser p, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
String text = p.getText();
return new ObjectMapper().readValue(text, Mail.class);
}
}
在您的類上添加一些注釋,如下所示:
@Data
@JsonNaming(PropertyNamingStrategy.UpperCamelCaseStrategy.class)
public class MessageWrapper {
private String type;
private String messageId;
private String topicArn;
@JsonDeserialize(using = NotificationDeserializer.class)
private Notification message;
private Date timestamp;
private String signatureVersion;
private String signature;
private String signingCertURL;
private String unsubscribeURL;
}
@Data
public class Notification {
private String notificationType;
@JsonDeserialize(using = MailDeserializer.class)
private Mail mail;
}
@Data
public class Mail {
private String messageId;
private String source;
private String sourceArn;
private String sourceIp;
private String sendingAccountId;
private String[] destination;
}
編輯1
實際上并不MailDeserializer需要。獨自NotificationDeserializer解決這個問題。
編輯2
在自定義解串器中使用新的ObjectMapper是必須的。

TA貢獻1812條經驗 獲得超5個贊
messageproperty 的類型為 type Notification,但Jackson預期JSON Object不是string value。在這種情況下,您可以創建自定義反序列化器或通過某種環回實現來實現通用解決方案。如果給定的有效負載不是 aJSON Object將其讀取為 aString并使用 this 再次調用反序列化String。
為了避免StackOverflowError您需要使用另一個實例ObjectMapper或使用BeanDeserializerModifier保留BeanDeserializer實例并在遇到的地方使用它JSON Object。簡單的例子如下所示:
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.databind.BeanDescription;
import com.fasterxml.jackson.databind.DeserializationConfig;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategy;
import com.fasterxml.jackson.databind.annotation.JsonNaming;
import com.fasterxml.jackson.databind.deser.BeanDeserializer;
import com.fasterxml.jackson.databind.deser.BeanDeserializerBase;
import com.fasterxml.jackson.databind.deser.BeanDeserializerModifier;
import com.fasterxml.jackson.databind.module.SimpleModule;
import com.fasterxml.jackson.databind.node.TextNode;
import lombok.Data;
import lombok.ToString;
import java.io.File;
import java.io.IOException;
import java.util.Collections;
import java.util.Date;
import java.util.Objects;
import java.util.Set;
public class JsonApp {
public static void main(String[] args) throws Exception {
File jsonFile = new File("./resource/test.json").getAbsoluteFile();
SimpleModule loopBackModule = new SimpleModule();
loopBackModule.setDeserializerModifier(new LoopBackBeanDeserializerModifier(Collections.singleton(Notification.class)));
ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.registerModule(loopBackModule);
MessageWrapper wrapper = mapper.readValue(jsonFile, MessageWrapper.class);
System.out.println(wrapper.getMessage());
}
}
class LoopBackBeanDeserializerModifier extends BeanDeserializerModifier {
private final Set<Class> allowedClasses;
LoopBackBeanDeserializerModifier(Set<Class> allowedClasses) {
this.allowedClasses = Objects.requireNonNull(allowedClasses);
}
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config, BeanDescription beanDesc, JsonDeserializer<?> deserializer) {
if (allowedClasses.contains(beanDesc.getBeanClass())) {
return new LoopBackBeanDeserializer<>((BeanDeserializerBase) deserializer);
}
return deserializer;
}
}
class LoopBackBeanDeserializer<T> extends BeanDeserializer {
private final BeanDeserializerBase baseDeserializer;
protected LoopBackBeanDeserializer(BeanDeserializerBase src) {
super(src);
this.baseDeserializer = src;
}
@Override
public T deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
// if first token is VALUE_STRING we should read it as String and
// run deserialization process again based on this String.
if (p.currentToken() == JsonToken.VALUE_STRING) {
return (T) ((ObjectMapper) p.getCodec()).readValue(p.getText(), _valueClass);
}
// vanilla bean deserialization
return (T) baseDeserializer.deserialize(p, ctxt);
}
}
POJO型號是一樣的。您只需要列出您期望某些問題和loop-back機制適用于它們的類。
添加回答
舉報