当前位置: 首页 > 知识库问答 >
问题:

如何用jackson传递构造函数的参数?

郑桐
2023-03-14

我正在尝试使用杰克逊对物体进行去耳廓化

this.prepareCustomMapper().readValue(response.getBody(), EmailResponse.class);

我有一个例外:

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)

我知道这是因为这是我的构造函数:

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);
    }
}

所以,我的构造函数收到 HttpResponse 参数,我没有传递它,但我不知道该怎么做。我不能用空构造函数过度收费,因为我需要它以这种方式接收 HttpResponse 对象。当我调用 readValue() 方法时,有什么方法可以传递这个构造函数参数吗?或者在这种情况下最好的选择是什么?我感谢您的帮助。问候

共有2个答案

李意致
2023-03-14

您可以编写自定义反序列化程序:http://jackson.codehaus.org/1.5.7/javadoc/org/codehaus/jackson/map/annotate/JsonDeserialize.html

在这种情况下,您可以将任何想要的值传递到构造函数中。您需要在EmailResponse上添加@JsonDeserialize注释,如下所示:

@JsonDeserialize(using = EmailResponseDeserializer.class)

反序列化器实现示例:

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;
    }
}

您还需要注册自定义反序列化器:

ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(EmailResponse.class, new EmailResponseDeserializer(httpRespose));
mapper.registerModule(module);

一般来说,我会说通过将 HttpResponse 添加到 EmailRespose bean 中,您将一些不应该有任何实现的 DTO 对象添加一些实现。我认为将httpResponse设置为自定义反序列化程序然后将其设置为EmailResponse不是一个好主意,但没有什么可以阻止您这样做。

希望这有帮助。

何峰
2023-03-14

您可以使用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);
    }
}

输出:

Bean{field1='value1', field2=123, external=MyExternalObject}
 类似资料:
  • 问题内容: 我正在尝试使用杰克逊对物体进行去电 我有这个例外: 我知道这正在发生,因为这是我的构造函数: 因此,我的构造函数接收到HttpResponse参数,但我没有传递它,但我不知道该怎么做。我不能用一个空的构造函数过度计费,因为我需要以这种方式接收HttpResponse对象。当我调用readValue()方法时,有什么方法可以传递此构造函数参数?或者在这种情况下最好的选择是什么?我感谢您的

  • 问题内容: 我的工厂如下 这是Foo的定义: 好。我不确定如何使用Guice将此参数传递给Foo构造函数? 有任何想法吗? 问题答案: 所有“ Guice构造函数参数”答案在某种程度上似乎都不完整。这是一个完整的解决方案,包括用法: //在实现类上注释构造函数和辅助参数 //使用仅接受辅助参数的create()方法创建工厂接口。 // FooFactory接口没有显式的实现类(Guice Magi

  • 我试图将构造函数参数动态传递给Springboot框架中的一个bean。我已经使用context.getBean(class,arg...)在Spring中动态传递构造函数参数,但它没有成功获取值并显示默认值。我的代码有什么问题? 项目结构: 应用程序上下文.xml 应用 活动 输出:

  • 我正在初始化的代码: 如何根据 类型在我的 函数中启动 ? ps-getForObject是spring restTemplate的标准函数-http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/client/RestTemplate.html#getForObject-java.lang.Str

  • 问题内容: 我迷失在通用丛林中,请帮助我:)我有这样的事情: 据我认为,编译器应该实现,因为它实现了。 为什么会出现此错误? 我该如何工作? ps:如果您对此有更好的标题,请进行更改。我无法弥补。 问题答案: 问题是,您的构造函数需要一个,并且在您的代码中将其推断为。 因此,您应该通过,然后通过。但是您不能像那样直接传递该实例。 但是,您可以通过将类强制转换为所需实例来解决此问题: 请注意,如何首

  • 我正在尝试通过:如果流文件; 在我的主()中,到一个名为“FIFO”的类的构造函数:FIFO(文件); 在FIFO(FIFO.h)的头文件中,我有: 在FIFO.cc,我有: 我一直喜欢(还有更多,我只是粘贴其中一个): 在文件包括从/usr/lib/gcc/x86_64-redhat linux/4.4.7/…/…/…/…/包含/c /4.4.7/bits/localefwd.h: 43,从/u