jsc*_*man 2 java mapping serialization json jackson
我正在尝试使用 Jackson 对对象进行去锡化
this.prepareCustomMapper().readValue(response.getBody(), EmailResponse.class);
Run Code Online (Sandbox Code Playgroud)
我有这个例外:
org.codehaus.jackson.map.JsonMappingException: No suitable constructor found for type [simple type, class com.despegar.social.automation.services.emailservice.response.EmailResponse]: can not instantiate from JSON object (need to add/enable type information?)
at [Source: java.io.StringReader@4f38f663; line: 1, column: 12] (through reference chain: com.despegar.social.automation.services.emailservice.response.EmailsResponse["items"])
at org.codehaus.jackson.map.JsonMappingException.from(JsonMappingException.java:163)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObjectUsingNonDefault(BeanDeserializer.java:746)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:683)
at org.codehaus.jackson.map.deser.BeanDeserializer.deserialize(BeanDeserializer.java:580)
at org.codehaus.jackson.map.deser.std.CollectionDeserializer.deserialize(CollectionDeserializer.java:217)
Run Code Online (Sandbox Code Playgroud)
我知道这是因为这是我的构造函数:
public class EmailResponse extends MyServiceResponse {
private String id;
private String user_id;
private String email;
private Boolean is_primary;
private Boolean is_confirmed;
public EmailResponse(HttpResponse request) {
super(request);
}
}
Run Code Online (Sandbox Code Playgroud)
所以,我的构造函数收到 HttpResponse 参数,但我没有传递它,但我不知道该怎么做。我不能用空的构造函数过度充电,因为我需要它以这种方式接收 HttpResponse 对象。当我调用 readValue() 方法时,有没有办法传递这个构造函数参数?或者在这种情况下最好的选择是什么?我感谢您的帮助。问候
您可以编写自定义解串器:http : //jackson.codehaus.org/1.5.7/javadoc/org/codehaus/jackson/map/annotate/JsonDeserialize.html
在这种情况下,您将能够将所需的任何值传递给构造函数。您需要在 EmailResponse 上添加 @JsonDeserialize 注释,例如:
@JsonDeserialize(using = EmailResponseDeserializer.class)
Run Code Online (Sandbox Code Playgroud)
解串器实现示例:
public class EmailResponseDeserializer extends JsonDeserializer<EmailResponse> {
HttpResponse httpResponse;
public EmailResponceDeserializer(HttpResponse httpResponse) {
this.httpResponse = httpResponse;
}
@Override
public EmailResponse deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
int id = (Integer) ((IntNode) node.get("id")).numberValue();
String email = node.get("email").asText();
EmailResponse emailResponse = new EmailResponse(httpResponse)
emailResponse.setId(id);
emailResponse.setEmail(email);
// other properties
return emailResponse;
}
}
Run Code Online (Sandbox Code Playgroud)
您还需要注册自定义解串器:
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(EmailResponse.class, new EmailResponseDeserializer(httpRespose));
mapper.registerModule(module);
Run Code Online (Sandbox Code Playgroud)
通常,我会说通过将 HttpResponse 添加到 EmailRespose bean 中,您将一些实现添加到不应该有的 DTO 对象中。我不认为将 httpResponse 设置到自定义反序列化器中然后将其设置到 EmailResponse 中不是一个好主意,但没有什么可以阻止您这样做。
希望这可以帮助。
您可以使用Jackson 值注入功能将不属于输入 JSON 的对象引用作为构造函数参数传递。下面是一个例子:
public class JacksonInjectExample {
private static final String JSON = "{\"field1\":\"value1\", \"field2\":123}";
// HttpResponse in your case
public static class ExternalObject {
@Override
public String toString() {
return "MyExternalObject";
}
}
public static class Bean {
// make fields public to avoid writing getters in this example
public String field1;
public int field2;
private ExternalObject external;
public Bean(@JacksonInject final ExternalObject external) {
this.external = external;
}
@Override
public String toString() {
return "Bean{" +
"field1='" + field1 + '\'' +
", field2=" + field2 +
", external=" + external +
'}';
}
}
public static void main(String[] args) throws IOException {
final ObjectMapper mapper = new ObjectMapper();
final InjectableValues.Std injectableValues = new InjectableValues.Std();
injectableValues.addValue(ExternalObject.class, new ExternalObject());
mapper.setInjectableValues(injectableValues);
final Bean bean = mapper.readValue(JSON, Bean.class);
System.out.println(bean);
}
}
Run Code Online (Sandbox Code Playgroud)
输出:
Bean{field1='value1', field2=123, external=MyExternalObject}
Run Code Online (Sandbox Code Playgroud)