JAVA對象和BSON文檔對象之間的相互轉(zhuǎn)換

支持 列表蜗巧,哈希,數(shù)組和基本類型

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.TypeVariable;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

import org.bson.Document;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.data.annotation.Transient;

public class BsonUtil {
    private static Logger logger = LoggerFactory.getLogger(BsonUtil.class);
    
     public static <T> List<T> toBeans(List<Document> documents, Class<T> clazz){
        List<T> list = new ArrayList<T>();
        for (int i = 0; null != documents && i < documents.size(); i++) {
            list.add(toBean(documents.get(i), clazz));
        }
        return list;
    }

    @SuppressWarnings({ "rawtypes", "unused", "unchecked" })
    public static <T> T toBean(Document document,Class<T> clazz) {
        T entity = null;
        try {
            entity = (T)clazz.newInstance();
            
            Field[] fields = clazz.getDeclaredFields();
            
            for (Field field : fields) {
                if(Modifier.isStatic(field.getModifiers())) {
                    continue;//靜態(tài)成員不轉(zhuǎn)換
                }
                field.setAccessible(true);
                Class fieldClazz = field.getType();
                String key = field.getName();
                
                if("id".equals(key)) {
                    key = "_id";
                }
                Object value = null;
                try {
                    value = field.get(entity);
                } catch (Exception e) {
                    e.printStackTrace();
                }
                Object val = document.get(key);
                if(val == null) {
                    continue;
                }
                if(isPrimitive(fieldClazz) || fieldClazz == String.class) {
                    if(field!=null) field.set(entity, val);
                    continue;
                }
                //數(shù)組
                if(fieldClazz.isArray()) {
                    String itemClazzName = fieldClazz.getTypeName().substring(0, fieldClazz.getTypeName().length()-2);
                    
                    Class itemClazz = null;
                    try {
                        itemClazz = Class.forName(itemClazzName);
                    } catch (ClassNotFoundException e) {
                        //此時(shí)為基本類型
                        itemClazz = toPrimitiveClass(itemClazzName);
                    }
                    Object array = toArray(document.get(key),itemClazz);
                    if(field!=null) field.set(entity, array);
                    continue;
                }
                //列表
                if (List.class.isAssignableFrom(fieldClazz)) {
                    ParameterizedType fc = (ParameterizedType)field.getGenericType();
                    TypeVariable[] types = fieldClazz.getTypeParameters();
                    List list = (List)value;
                    if(value == null) {
                        list = new ArrayList<>();
                        if(field!=null) field.set(entity, list);
                    }
                    toList(document.get(key), list, (Class)fc.getActualTypeArguments()[0]);
                    continue;
                }
                //哈希表
                if(Map.class.isAssignableFrom(fieldClazz)) {
                    ParameterizedType fc = (ParameterizedType)field.getGenericType();
                    Map map = (Map) value;
                    if(value == null) {
                        map = new HashMap<>();
                        if(field!=null) field.set(entity, map);
                    }
                    toMap(document.get(key), map, (Class)fc.getActualTypeArguments()[0],(Class)fc.getActualTypeArguments()[1]);
                    continue;
                }
                document.put(key, toBean((Document)val, fieldClazz));
            }
        } catch (Exception e) {
            logger.error("toBean() error , clazz:"+clazz.getName(), e);
        } 
        
        
        return entity;
    }
    /**
     * 轉(zhuǎn)換成適合update語句的Document對象
     * @param entity
     * @return
     */
    public static Document toDocumentForUpdate(Object entity) {
        Document document = new Document();
        document.put("$set", toDocument(entity));
        return document;
    }
    /**
     * 轉(zhuǎn)換成Document
     * @param entity
     * @return
     */
    @SuppressWarnings({ "rawtypes", "unchecked" })
    public static Document toDocument(Object entity) {
        if(entity == null) {
            return null;
        }
        
        Document document = new Document();
        Class clazz = entity.getClass();
        
        Field[] fields = clazz.getDeclaredFields();
        
        for (Field field : fields) {
            if(Modifier.isStatic(field.getModifiers())) {
                continue;//靜態(tài)成員不轉(zhuǎn)換
            }
            field.setAccessible(true);
            Class fieldClazz = field.getType();
            if(fieldClazz.getAnnotationsByType(Transient.class).length>0) {
                //@Transient 標(biāo)識的屬性不進(jìn)行轉(zhuǎn)換
                continue;
            }
            
            String key = field.getName();
            if("id".equals(key)) {
                key = "_id";
            }
            Object value = null;
            try {
                value = field.get(entity);
            } catch (Exception e) {
                e.printStackTrace();
            }
            if(value == null) {
                continue;
            }
            try {
                if(isPrimitive(fieldClazz) || fieldClazz == String.class) {
                    document.put(key, value);
                    continue;
                }
            
                if(fieldClazz.isArray()) { //數(shù)組
                    String itemClazzName = fieldClazz.getTypeName().substring(0, fieldClazz.getTypeName().length()-2);
                    Class itemClazz = null;
                    try {
                        itemClazz = Class.forName(itemClazzName);
                    } catch (ClassNotFoundException e) {
                        //此時(shí)為基本類型
                        itemClazz = toPrimitiveClass(itemClazzName);
                    }
                    
                    int len = Array.getLength(value);
                    
                    if(isPrimitive(itemClazz) || itemClazz == String.class) {
                        List values = new ArrayList<>();
                        
                        for(int i=0;i<len;i++) {
                            Object object = Array.get(value, i);
                            values.add(object);
                        }
                        
                        document.put(key, values);
                    }else {
                        List<Document> listDocument = new ArrayList<>();
                        document.put(key, listDocument);
                        
                        for(int i=0;i<len;i++) {
                            Object object = Array.get(value, i);
                            listDocument.add(toDocument(object));
                        }
                    }
                    continue;
                }
                //列表
                if (List.class.isAssignableFrom(fieldClazz)) {
                    List list = (List)value;
                    ParameterizedType fc = (ParameterizedType)field.getGenericType();
                    Class itemClazz = (Class)fc.getActualTypeArguments()[0];
                    
                    if(isPrimitive(itemClazz) || itemClazz == String.class) {
                        List values = new ArrayList<>();
                        for (Object object : list) {
                            values.add(object);
                        }
                        document.put(key, values);
                    }else {
                        List<Document> listDocument = new ArrayList<>();
                        document.put(key, listDocument);
                        for (Object object : list) {
                            listDocument.add(toDocument(object));
                        }
                    }
                    continue;
                }
                
                //哈希表
                if (Map.class.isAssignableFrom(fieldClazz)) {
                    Map map = (Map)field.get(entity);
                    Set<Map.Entry> entries = map.entrySet();
                    Map mpperMap = new HashMap<>();
                    document.put(key, mpperMap);
                    
                    ParameterizedType fc = (ParameterizedType)field.getGenericType();
                    Class keyClazz = (Class)fc.getActualTypeArguments()[0];
                    if(keyClazz != String.class && !isPrimitive(keyClazz)) {
                        throw new RuntimeException("不支持的Map,轉(zhuǎn)換成document的key只能為基本類型或字符串");
                    }
                    Class itemClazz = (Class)fc.getActualTypeArguments()[1];
                    if(itemClazz == String.class || isPrimitive(itemClazz)) {
                        for (Map.Entry entry : entries) {
                            mpperMap.put(entry.getKey().toString(), entry.getValue());
                        }
                    }else {
                        for (Map.Entry entry : entries) {
                            mpperMap.put(entry.getKey().toString(), toDocument(entry.getValue()));
                        }
                    }
                    
//                  Document mapDocument = new Document();
//                  document.put(key, mapDocument);
//                  
//                  for (Map.Entry entry : entries) {
//                      Object object = entry.getValue();
//                      if(isPrimitive(object.getClass()) || object.getClass() == String.class) {
//                          mapDocument.put(entry.getKey().toString(), object);
//                      }else {
//                          mapDocument.put(entry.getKey().toString(), toDocument(object));
//                      }
//                  }
                    continue;
                }
                document.put(key, toDocument(value));
            }catch (Exception e) {
                logger.error("toDocument() , error clazz="+entity.getClass().getName(),e);
            }
        }
        return document;
    }
    
    @SuppressWarnings("rawtypes")
    private static boolean isPrimitive(Class clazz) {
        if(clazz.isPrimitive()) {
            return true;
        }
        if(Long.class == clazz || Integer.class == clazz || Double.class == clazz || Float.class == clazz || Short.class == clazz || Boolean.class == clazz) {
            return true;
        }
        return false;
    }
    
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static Object toArray(Object value, Class itemClazz) {
        List list = (List)value;
        
        Object array = Array.newInstance(itemClazz, list.size());
        int i = 0;
        for (Object object : list) {
            if(object instanceof Document) {
                Array.set(array, i++, toBean((Document)object,itemClazz));
            }else {
                Array.set(array, i++, object);
            }
        }
        return array;
    }
    @SuppressWarnings({ "unchecked", "rawtypes" })
    private static void toMap(Object value , Map map,Class keyClazz,Class itemClazz) throws InstantiationException, IllegalAccessException {
        Set<Map.Entry> entries = ((Map)value).entrySet();
        for (Map.Entry entry : entries) {
            Object keyV = entry.getKey().getClass() == String.class ? entry.getKey() : toPrimitive(entry.getKey().toString(), keyClazz);
            Object itemV = entry.getValue();
            if(itemV instanceof Document) {
                map.put(keyV, toBean((Document)itemV,itemClazz));
            }else {
                map.put(keyV,itemV);
            }
        }
        
//      Document document = (Document) value;
//      for (Map.Entry entry : document.entrySet()) {
//          Object keyV = toPrimitive(entry.getKey().toString(), keyClazz);
//          Object itemV = document.get(entry.getKey());
//          
//          if(itemV instanceof Document) {
//              map.put(keyV, toBean((Document)itemV,itemClazz));
//          }else {
//              map.put(keyV,itemV);
//          }
//          
//      }
    }
    
    @SuppressWarnings("rawtypes")
    private static Object toPrimitive(String value,Class clazz) {
        if(int.class == clazz || Integer.class == clazz) {
            return Integer.valueOf(value);
        }else if(long.class == clazz || Long.class == clazz) {
            return Long.valueOf(value);
        }else if(short.class == clazz || Short.class == clazz) {
            return Short.valueOf(value);
        }else if(double.class == clazz || Double.class == clazz) {
            return Double.valueOf(value);
        }else if(float.class == clazz || Float.class == clazz) {
            return Float.valueOf(value);
        }else if(boolean.class == clazz || Boolean.class == clazz) {
            return Boolean.valueOf(value);
        }else {
            throw new RuntimeException("Map key nonsupport !!!");
        }
    }
    @SuppressWarnings("rawtypes")
    private static Class toPrimitiveClass(String primitiveClazzName) {
        Class itemClazz = null;
        //此時(shí)為基本類型
        if("long".equals(primitiveClazzName)) {
            itemClazz = long.class;
        }else if("int".equals(primitiveClazzName)) {
            itemClazz = int.class;
        }else if("short".equals(primitiveClazzName)) {
            itemClazz = short.class;
        }else if("double".equals(primitiveClazzName)) {
            itemClazz = double.class;
        }else if("float".equals(primitiveClazzName)) {
            itemClazz = float.class;
        }else if("boolean".equals(primitiveClazzName)) {
            itemClazz = boolean.class;
        }else {
            throw new RuntimeException("nonsupport type !!!");
        }
        return itemClazz;
    }
    @SuppressWarnings({ "rawtypes", "unchecked" })
    private static void toList(Object value , List list,Class itemClazz) throws InstantiationException, IllegalAccessException {
        if(value.getClass() == Document[].class) {
            Document[] documents = (Document[])value;
            for (Document document : documents) {
                list.add(toBean(document, itemClazz));
            }
        }else {
            List vals = (List)value;
            for (Object object : vals) {
                list.add(object);
            }
        }
    }
}

測試類

public class A{
        
        private int int1;
        private Long long1;
        
        private String str1;
        
        private boolean bool1;
        
        private short short1;
        
        private double double1;
        private float float1;
        
        private B[] bs;
        private long[] longArr;
        
        private Double[] doubleArr;
        private List<B> bList = new ArrayList<>();
        
        private Map<Integer, B> bMap = new HashMap<>();
        
        private List<Integer> ints = new ArrayList<>();
        private Map<Integer, Integer> intMap = new HashMap<>();
        
        private List<String> strings = new ArrayList<>();
        
        private List<Long> longs = new ArrayList<>();
        
        private Date date = new Date();
        public int getInt1() {
            return int1;
        }
        public void setInt1(int int1) {
            this.int1 = int1;
        }
        public Long getLong1() {
            return long1;
        }
        public void setLong1(Long long1) {
            this.long1 = long1;
        }
        public String getStr1() {
            return str1;
        }
        public void setStr1(String str1) {
            this.str1 = str1;
        }
        public boolean isBool1() {
            return bool1;
        }
        public void setBool1(boolean bool1) {
            this.bool1 = bool1;
        }
        public short getShort1() {
            return short1;
        }
        public void setShort1(short short1) {
            this.short1 = short1;
        }
        public double getDouble1() {
            return double1;
        }
        public void setDouble1(double double1) {
            this.double1 = double1;
        }
        public float getFloat1() {
            return float1;
        }
        public void setFloat1(float float1) {
            this.float1 = float1;
        }
        public B[] getBs() {
            return bs;
        }
        public void setBs(B[] bs) {
            this.bs = bs;
        }
        public List<B> getbList() {
            return bList;
        }
        public void setbList(List<B> bList) {
            this.bList = bList;
        }
        public Map<Integer, B> getbMap() {
            return bMap;
        }
        public void setbMap(Map<Integer, B> bMap) {
            this.bMap = bMap;
        }
        public List<Integer> getInts() {
            return ints;
        }
        public void setInts(List<Integer> ints) {
            this.ints = ints;
        }
        public Map<Integer, Integer> getIntMap() {
            return intMap;
        }
        public void setIntMap(Map<Integer, Integer> intMap) {
            this.intMap = intMap;
        }
        public List<String> getStrings() {
            return strings;
        }
        public void setStrings(List<String> strings) {
            this.strings = strings;
        }
        public List<Long> getLongs() {
            return longs;
        }
        public void setLongs(List<Long> longs) {
            this.longs = longs;
        }
        public long[] getLongArr() {
            return longArr;
        }
        public void setLongArr(long[] longArr) {
            this.longArr = longArr;
        }
        public Double[] getDoubleArr() {
            return doubleArr;
        }
        public void setDoubleArr(Double[] doubleArr) {
            this.doubleArr = doubleArr;
        }
        
        public Date getDate() {
            return date;
        }
        public void setDate(Date date) {
            this.date = date;
        }
        @Override
        public String toString() {
            return "A [int1=" + int1 + ", long1=" + long1 + ", str1=" + str1 + ", bool1=" + bool1 + ", short1=" + short1
                    + ", double1=" + double1 + ", float1=" + float1 + ", bs=" + Arrays.toString(bs) + ", longArr="
                    + Arrays.toString(longArr) + ", doubleArr=" + Arrays.toString(doubleArr) + ", bList=" + bList
                    + ", bMap=" + bMap + ", ints=" + ints + ", intMap=" + intMap + ", strings=" + strings + ", longs="
                    + longs + ", date=" + date + "]";
        }
        
    }

    public class B {
        Integer intB;
        Long longB;
        String strB;
        public Integer getIntB() {
            return intB;
        }
        public void setIntB(Integer intB) {
            this.intB = intB;
        }
        public Long getLongB() {
            return longB;
        }
        public void setLongB(Long longB) {
            this.longB = longB;
        }
        public String getStrB() {
            return strB;
        }
        public void setStrB(String strB) {
            this.strB = strB;
        }
        @Override
        public String toString() {
            return "B [intB=" + intB + ", longB=" + longB + ", strB=" + strB + "]";
        }
    }

測試用例

public class BsonUseCase {

    @Test
    public void testMongodbInsert() {
        MongoClient mongoClient = new MongoClient("localhost");
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> collection = database.getCollection("test_a");        

        Document document = BsonUtil.toDocument(getA());
        System.out.println(document);
        collection.insertOne(document);
    }
    
    @Test
    public void testMongodbQuery() {
        String id = "5cb21a21e2713f598f57ccb2"; //根據(jù)插入的主鍵修改
        MongoClient mongoClient = new MongoClient("localhost");
        MongoDatabase database = mongoClient.getDatabase("test");
        MongoCollection<Document> collection = database.getCollection("test_a");
        FindIterable<Document> findIterable =  collection.find(Filters.eq("_id", new ObjectId(id)));
        Document document = findIterable.first();
        System.out.println(document);
        System.out.println("對比");
        System.out.println(BsonUtil.toDocument(getA()));
        
    }
    
    @Test
    public void testToBean() {
        A a = getA();
        Document document = BsonUtil.toDocument(a);
        System.out.println(document);
        System.out.println("before:");
        System.out.println(a);
        System.out.println("After:");
        A aa = BsonUtil.toBean(document, A.class);
        System.out.println(aa);
    }
    @Test
    public void testToDocument() {
        
        Document document = BsonUtil.toDocument(getA());
        System.out.println(document);
    }
    
    private A  getA() {
        A a = new A();
        a.setInt1(11);
        a.setBool1(true);
        a.setDouble1(12323.4434D);
        a.setFloat1(323.23f);
        a.setLong1(12443344444L);
        a.setShort1((short)323);
        a.setStr1("Hello,BSON");
        
        B b = new B();
        b.setIntB(2001);
        b.setLongB(2000000001L);
        b.setStrB("2BBBBBBBBBBBBBBBBBBBBBB1");
        
        B b2 = new B();
        b2.setIntB(2003);
        b2.setLongB(2000000003L);
        b2.setStrB("2BBBBBBBBBBBBBBBBBBBBBB2");
        
        a.setBs(new B[] {b,b2});
        
        long[] longArr = new long[] {1332L,3444L,5677L};
        a.setLongArr(longArr);
        
        Double[] doubleArr = new Double[] {33.32D,4345.3D};
        a.setDoubleArr(doubleArr);
        
        List<B> bList = new ArrayList<>();
        bList.add(b);
        bList.add(b2);
        
        a.setbList(bList);
        
        a.getbMap().put(b.getIntB(), b);
        a.getbMap().put(b2.getIntB(), b2);
        
        
        a.getInts().add(11);
        a.getInts().add(22);
        a.getInts().add(33);
        
        a.getIntMap().put(111, 111);
        a.getIntMap().put(222, 222);
        a.getIntMap().put(333, 333);
        a.getIntMap().put(444, 444);
        
        a.getStrings().add("eweew");
        a.getStrings().add("eeeeee");
        
        a.getLongs().add(2334444L);
        a.getLongs().add(2334445L);
        a.getLongs().add(2334446L);
        a.getLongs().add(2334447L);
        return a;
    }
}

測試結(jié)果

對比測試用例輸出結(jié)果牙捉,一切正常 !敬飒!

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末邪铲,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子无拗,更是在濱河造成了極大的恐慌带到,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,270評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件英染,死亡現(xiàn)場離奇詭異揽惹,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)税迷,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,489評論 3 395
  • 文/潘曉璐 我一進(jìn)店門永丝,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人箭养,你說我怎么就攤上這事「珉梗” “怎么了毕泌?”我有些...
    開封第一講書人閱讀 165,630評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長嗅辣。 經(jīng)常有香客問我撼泛,道長,這世上最難降的妖魔是什么澡谭? 我笑而不...
    開封第一講書人閱讀 58,906評論 1 295
  • 正文 為了忘掉前任愿题,我火速辦了婚禮,結(jié)果婚禮上蛙奖,老公的妹妹穿的比我還像新娘潘酗。我一直安慰自己,他們只是感情好雁仲,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,928評論 6 392
  • 文/花漫 我一把揭開白布仔夺。 她就那樣靜靜地躺著,像睡著了一般攒砖。 火紅的嫁衣襯著肌膚如雪缸兔。 梳的紋絲不亂的頭發(fā)上日裙,一...
    開封第一講書人閱讀 51,718評論 1 305
  • 那天,我揣著相機(jī)與錄音惰蜜,去河邊找鬼昂拂。 笑死,一個(gè)胖子當(dāng)著我的面吹牛抛猖,可吹牛的內(nèi)容都是我干的政钟。 我是一名探鬼主播,決...
    沈念sama閱讀 40,442評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼樟结,長吁一口氣:“原來是場噩夢啊……” “哼养交!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起瓢宦,我...
    開封第一講書人閱讀 39,345評論 0 276
  • 序言:老撾萬榮一對情侶失蹤碎连,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后驮履,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體鱼辙,經(jīng)...
    沈念sama閱讀 45,802評論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,984評論 3 337
  • 正文 我和宋清朗相戀三年玫镐,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了倒戏。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 40,117評論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡恐似,死狀恐怖杜跷,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情矫夷,我是刑警寧澤葛闷,帶...
    沈念sama閱讀 35,810評論 5 346
  • 正文 年R本政府宣布,位于F島的核電站双藕,受9級特大地震影響淑趾,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜忧陪,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,462評論 3 331
  • 文/蒙蒙 一扣泊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧嘶摊,春花似錦延蟹、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,011評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至蹂空,卻和暖如春俯萌,著一層夾襖步出監(jiān)牢的瞬間果录,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,139評論 1 272
  • 我被黑心中介騙來泰國打工咐熙, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留弱恒,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,377評論 3 373
  • 正文 我出身青樓棋恼,卻偏偏與公主長得像返弹,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子爪飘,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,060評論 2 355

推薦閱讀更多精彩內(nèi)容