How to pass constructor's parameters with jackson?

后端 未结 2 488
眼角桃花
眼角桃花 2020-12-20 00:54

i am trying to desearlize an object using Jackson

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

and i have

相关标签:
2条回答
  • 2020-12-20 01:22

    You can write your custom deserializer: http://jackson.codehaus.org/1.5.7/javadoc/org/codehaus/jackson/map/annotate/JsonDeserialize.html

    In that case you will be able to pass any values that you want into the constructor. You will need to add @JsonDeserialize annotation on EmailResponse like:

    @JsonDeserialize(using = EmailResponseDeserializer.class)
    

    Deserializer implementation example:

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

    Also you will need to register the custom deserializer:

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

    Generally, I would say that by adding HttpResponse into EmailRespose bean you are adding some implementation into the DTO object which shouldn't have any. I don't think that this is a good idea to set httpResponse into the custom deserialiser and then set it into the EmailResponse but nothing prevent you of doing it.

    Hope this helps.

    0 讨论(0)
  • 2020-12-20 01:27

    You can use the Jackson value injection feature to pass an object reference which is not a part of the input JSON as a constructor parameter. Here is an example:

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

    Output:

    Bean{field1='value1', field2=123, external=MyExternalObject}
    
    0 讨论(0)
提交回复
热议问题