美文网首页JAVA进阶
JAVA对象和BSON文档对象之间的相互转换

JAVA对象和BSON文档对象之间的相互转换

作者: 大华夏 | 来源:发表于2019-04-14 01:21 被阅读0次

    支持 列表,哈希,数组和基本类型

    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;//静态成员不转换
                    }
                    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;
                    }
                    //数组
                    if(fieldClazz.isArray()) {
                        String itemClazzName = fieldClazz.getTypeName().substring(0, fieldClazz.getTypeName().length()-2);
                        
                        Class itemClazz = null;
                        try {
                            itemClazz = Class.forName(itemClazzName);
                        } catch (ClassNotFoundException e) {
                            //此时为基本类型
                            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;
        }
        /**
         * 转换成适合update语句的Document对象
         * @param entity
         * @return
         */
        public static Document toDocumentForUpdate(Object entity) {
            Document document = new Document();
            document.put("$set", toDocument(entity));
            return document;
        }
        /**
         * 转换成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;//静态成员不转换
                }
                field.setAccessible(true);
                Class fieldClazz = field.getType();
                if(fieldClazz.getAnnotationsByType(Transient.class).length>0) {
                    //@Transient 标识的属性不进行转换
                    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()) { //数组
                        String itemClazzName = fieldClazz.getTypeName().substring(0, fieldClazz.getTypeName().length()-2);
                        Class itemClazz = null;
                        try {
                            itemClazz = Class.forName(itemClazzName);
                        } catch (ClassNotFoundException e) {
                            //此时为基本类型
                            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,转换成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;
            //此时为基本类型
            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"; //根据插入的主键修改
            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;
        }
    }
    

    测试结果

    对比测试用例输出结果,一切正常 !!

    相关文章

      网友评论

        本文标题:JAVA对象和BSON文档对象之间的相互转换

        本文链接:https://www.haomeiwen.com/subject/hwgdwqtx.html