如何在反序列化json对象列表的同时使用JacksonInject在List的构造函数中注入值

时间:2016-08-08 04:32:45

标签: json jackson

我在使用REST Web服务中的Jackson解析器进行反序列化时遇到了向POJO的参数化构造函数注入外部值的问题。我提到了以下链接,但它们没有多大帮助 - Injecting ObjectMapper into a deserialized object using @JacksonInject and @JsonCreator How to pass constructor's parameters with jackson?

我有一个班级,比如说A扩展了BaseClass。

import com.fasterxml.jackson.annotation.JacksonInject;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonGetter;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import java.util.List;
import java.util.Map;
import org.codehaus.jackson.annotate.JsonProperty;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.crypto.codec.Base64;
import org.springframework.stereotype.Repository;

@Repository
@JsonInclude(Include.NON_NULL)
public class A extends BaseClass {

    private String contentType;
    private String size;
    private String data;   

    /**
     *
     * @return
     */
    public String getData() {
        return data;
    }

    /**
     *
     * @param data
     */
    public void setData(String data) {
        this.data = data;
    }


    /**
     *
     * @return
     */
    public String getContentType() {
        return contentType;
    }

    /**
     *
     * @param contentType
     */
    public void setContentType(String contentType) {
        this.contentType = contentType;
    }


    /**
     *
     * @param size
     */
    public void setSize(String size) {
        this.size = size;
    }
}



import java.util.HashMap;
import java.util.Map;
import org.springframework.stereotype.Component;

@Component
public abstract class BaseClass {

    private String id;    

    /**
     *
     * @return
     */
    public String getId() {
        return id;
    }

    /**
     *
     * @param id
     */
    public void setId(String id) {
        this.id = id;
    }   

    }

我的输入Json -

{
"data":  { 
       "object" : [
            {
            "id"   : "1234",
            "contentType" : "text",        
            "size"            : "1024",
            "data"            : "testdata"
        },
            {
            "id"   : "123",
            "contentType" : "text",        
            "size"            : "1024",
            "data"            : "testdata"
        },
            {
            "id"   : "342",
            "contentType" : "text",        
            "size"            : "1024",
            "data"            : "testdata"
        }
              ]                                     
         }

}

我有一个GetJsonMessage类,我将这个A对象列表转换为自定义类AList,它扩展了ArrayList类。我有其他类似于A的类,因此在AList中使用泛型。

import com.fasterxml.jackson.annotation.JacksonInject;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.RecoverableDataAccessException;
import org.springframework.stereotype.Component;

@Component
public class AList<T extends BaseClass> extends ArrayList {

    @JacksonInject
    private  String key;

    public AList(@JacksonInject final String key){
    this.key = key;
    }

    public AList(){}


    /**
     * Searches objects in DB
     *
     * @return List of BaseClass
     *
     */
    public List<BaseClass> search() throws Exception {

        ..........
    }
}

现在GetJsonMessage类 -

import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.databind.InjectableValues;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.stereotype.Component;


@Component
public class GetJsonMessage<T extends BaseClass> {

    private Map<String, List<T>> data = new HashMap<>();
    @JsonIgnore
    private final ObjectMapper mapper = new ObjectMapper();
    @JsonIgnore
    private final InjectableValues.Std injectableValues = new InjectableValues.Std();


    /**
     *
     * @return
     */
    public Map<String, List<T>> getData() {
        return data;
    }

    /**
     *
     * @param data
     */
    public void setData(Map<String, List<T>> data) {
        this.data = data;
    }

    /**
     *
     * @param key
     * @param value
     */
    public void setData(String key, List<T> value) {
        this.data.put(key, value);
    }

    /**
     *
     * @param aClass
     * @return
     * @throws IOException
     */
    public AList<T> getObjectList(String key, Class<? extends BaseClass> aClass) throws IOException {
         injectableValues.addValue(String.class, key);
         mapper.setInjectableValues(injectableValues);
        AList<T> aList = mapper.readValue(mapper.writeValueAsString(data.get(key)), mapper.getTypeFactory().constructCollectionType(AList.class, aClass));
        return aList;        
    }
}

最后我的控制器 -

public JsonResponse searchObjects(@RequestBody GetJsonMessage<A> jsonMessage,
            @RequestParam Map<String, String> query) throws Exception {

       AList<A> aList = jsonMessage.getObjectList("object", A.class);
       aList.search();
    }

当我执行时,我没有看到&#34; key&#34;设置进入AList类,也没有例外。

但是,如果我尝试通过将代码更改为下面来注入A类中的键,则会出现错误 -

  

错误:com.fasterxml.jackson.databind.JsonMappingException:没有   &#39; injectableValues&#39;配置后,无法使用id注入值   [java.lang.String中]

 @Repository
    @JsonInclude(Include.NON_NULL)
    public class A extends BaseClass {

        private String contentType;
        private String size;
        private String data;
        private String key;

 @JsonCreator
    public A(@JacksonInject final String key){
    this.key = key;
    }

    public A(){}   

        /**
         *
         * @return
         */
        public String getData() {
            return data;
        }

        /**
         *
         * @param data
         */
        public void setData(String data) {
            this.data = data;
        }
/**
         *
         * @return
         */
        public String getKey() {
            return key;
        }

        /**
         *
         * @param data
         */
        public void setKey(String key) {
            this.key= key;
        }


        /**
         *
         * @return
         */
        public String getContentType() {
            return contentType;
        }

        /**
         *
         * @param contentType
         */
        public void setContentType(String contentType) {
            this.contentType = contentType;
        }


        /**
         *
         * @param size
         */
        public void setSize(String size) {
            this.size = size;
        }
    }

无论哪种方式,我都无法将此外部属性注入到AList或A的构造函数中。

我使用的是jackson版本2.1.1

我不想使用CustomDeserializer,因为它不适合我有多个继承BaseClass的对象。

任何帮助将不胜感激。提前谢谢。

0 个答案:

没有答案