• 10月31 外部导入数据,配置映射关系,转为我们需要的实体


    1、pom里引入net.sf.json

     <dependency>
            <groupId>net.sf.json-lib</groupId>
            <artifactId>json-lib</artifactId>
            <classifier>jdk15</classifier>
            <version>2.2.3</version>
    </dependency>

    2、外部导入数据,配置映射关系,转为我们需要的实体

    2.1 读取json文件得到字符串

    public static String readFile(String srcPath) {
            InputStream input = null;
            StringBuilder out = null;
            try {
                input = TestUtil.class.getResource(srcPath).openStream();
    
                out = new StringBuilder();
                byte[] b = new byte[4096];
                for (int n; (n = input.read(b)) != -1; ) {
                    out.append(new String(b, 0, n));
                }
            } catch (Exception e) {
    
            } finally {
                try {
                    if (null != input) {
                        input.close();
                    }
                } catch (Exception e) {
    
                }
            }
            if (null != out && out.length() > 0) {
                return out.toString();
            }
            return "";
        }

    完整类

    import com.alibaba.fastjson.JSONObject;
    import com.fasterxml.jackson.annotation.JsonInclude;
    import com.fasterxml.jackson.databind.ObjectMapper;
    import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
    import org.hamcrest.Description;
    import org.hamcrest.TypeSafeDiagnosingMatcher;
    import org.springframework.http.MediaType;
    
    import java.io.IOException;
    import java.io.InputStream;
    import java.lang.reflect.InvocationTargetException;
    import java.nio.charset.Charset;
    import java.time.ZonedDateTime;
    import java.time.format.DateTimeParseException;
    import java.util.List;
    
    import static org.assertj.core.api.Assertions.assertThat;
    
    /**
     * Utility class for testing REST controllers.
     */
    public class TestUtil {
    
        public static final MediaType APPLICATION_JSON_UTF8 = new MediaType(
            MediaType.APPLICATION_JSON.getType(),
            MediaType.APPLICATION_JSON.getSubtype(), Charset.forName("utf8"));
    
        private TestUtil() {
        }
    
        /**
         * Convert an object to JSON byte array.
         *
         * @param object
         *            the object to convert
         * @return the JSON byte array
         * @throws IOException
         */
        public static byte[] convertObjectToJsonBytes(Object object)
            throws IOException {
            ObjectMapper mapper = new ObjectMapper();
            mapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    
            JavaTimeModule module = new JavaTimeModule();
            mapper.registerModule(module);
    
            return mapper.writeValueAsBytes(object);
        }
    
        /**
         * Create a byte array with a specific size filled with specified data.
         *
         * @param size the size of the byte array
         * @param data the data to put in the byte array
         * @return the JSON byte array
         */
        public static byte[] createByteArray(int size, String data) {
            byte[] byteArray = new byte[size];
            for (int i = 0; i < size; i++) {
                byteArray[i] = Byte.parseByte(data, 2);
            }
            return byteArray;
        }
    
        /**
         * A matcher that tests that the examined string represents the same instant as the reference datetime.
         */
        public static class ZonedDateTimeMatcher extends TypeSafeDiagnosingMatcher<String> {
    
            private final ZonedDateTime date;
    
            public ZonedDateTimeMatcher(ZonedDateTime date) {
                this.date = date;
            }
    
            @Override
            protected boolean matchesSafely(String item, Description mismatchDescription) {
                try {
                    if (!date.isEqual(ZonedDateTime.parse(item))) {
                        mismatchDescription.appendText("was ").appendValue(item);
                        return false;
                    }
                    return true;
                } catch (DateTimeParseException e) {
                    mismatchDescription.appendText("was ").appendValue(item)
                        .appendText(", which could not be parsed as a ZonedDateTime");
                    return false;
                }
    
            }
    
            @Override
            public void describeTo(Description description) {
                description.appendText("a String representing the same Instant as ").appendValue(date);
            }
        }
    
        /**
         * Creates a matcher that matches when the examined string reprensents the same instant as the reference datetime
         *
         * @param date the reference datetime against which the examined string is checked
         */
        public static ZonedDateTimeMatcher sameInstant(ZonedDateTime date) {
            return new ZonedDateTimeMatcher(date);
        }
    
        /**
         * Verifies the equals/hashcode contract on the domain object.
         */
        @SuppressWarnings("unchecked")
        public static void equalsVerifier(Class clazz) throws NoSuchMethodException, SecurityException, InstantiationException, IllegalAccessException,
            IllegalArgumentException, InvocationTargetException
    
        {
            Object domainObject1 = clazz.getConstructor().newInstance();
            assertThat(domainObject1.toString()).isNotNull();
            assertThat(domainObject1).isEqualTo(domainObject1);
            assertThat(domainObject1.hashCode()).isEqualTo(domainObject1.hashCode());
            // Test with an instance of another class
            Object testOtherObject = new Object();
            assertThat(domainObject1).isNotEqualTo(testOtherObject);
            // Test with an instance of the same class
            Object domainObject2 = clazz.getConstructor().newInstance();
            assertThat(domainObject1).isNotEqualTo(domainObject2);
            // HashCodes are equals because the objects are not persisted yet
            assertThat(domainObject1.hashCode()).isEqualTo(domainObject2.hashCode());
        }
    
        public static <T> T parseFile(String srcPath, Class<T> clazz) throws IOException {
            InputStream is = TestUtil.class.getResource(srcPath).openStream();
            T result = JSONObject.parseObject(is, clazz);
            is.close();
            return result;
        }
    
        public static <T> List<T> readList(String srcPath, Class<T> clazz) throws IOException, ClassNotFoundException {
            String text = readFile(srcPath);
            return JSONConvertUtil.toJavaArray(text, "_class");
        }
    
        public static String readFile(String srcPath) {
            InputStream input = null;
            StringBuilder out = null;
            try {
                input = TestUtil.class.getResource(srcPath).openStream();
    
                out = new StringBuilder();
                byte[] b = new byte[4096];
                for (int n; (n = input.read(b)) != -1; ) {
                    out.append(new String(b, 0, n));
                }
            } catch (Exception e) {
    
            } finally {
                try {
                    if (null != input) {
                        input.close();
                    }
                } catch (Exception e) {
    
                }
            }
            if (null != out && out.length() > 0) {
                return out.toString();
            }
            return "";
        }
    
    }
    View Code

    测试

     String jsonString = TestUtil.readFile("/test_data/member.json");

    2.2 转换

    1、实体

    public class DataAttribute {
        /**
         * 原来的属性
         */
        private String sourceName;
        
        /** 我们需要的属性 */
        private String fieldName;
        
        /** 数据的类型 */
        private AttributeDataType dataType;
        
        /** 默认值 */
        private String defaultValue;
    public class DataStrategy {
        
        private String id;
        /**
         * 是否有转换 true false 留作判断是否需要转换
         */
        private boolean mapping;
    
        private List<DataAttribute> attributes;
    View Code

    枚举

    public enum AttributeDataType {
        STRING, INTEGER, LONG, DATE, BOOLEAN,;
    }

    转换工具类

    package com.datatrategy;
    
    import java.lang.reflect.ParameterizedType;
    import java.util.HashMap;
    import java.util.List;
    import java.util.Map;
    import java.util.Set;
    
    import com.alibaba.fastjson.JSONObject;
    
    public class DataConvertor<T> {
        private Class<T> tClass;
        
        /**
         * 转换成内部数据结构
         * @param tenant 租户ID
         * @param strategy 转换策略
         * @param jsonData 源数据
         * @return 目标对象
         */
        public T toInternal(DataStrategy strategy, String jsonData) {
            List<DataAttribute> attributes = strategy.getAttributes();
    
            JSONObject json = JSONObject.parseObject(jsonData);
    
            JSONObject result = new JSONObject();
            for (DataAttribute attribute : attributes) {
                result.put(attribute.getFieldName(), mappingInternal(json, attribute));
            }
    
            Map<String, Object> itemMap = JSONObject.toJavaObject(json, Map.class);
            Map extension = new HashMap<>();
            Set<String> keySet = itemMap.keySet();
            for (String key : keySet) {
                boolean flag = false;
                for (DataAttribute attribute : attributes) {
                    if(key.equals(attribute.getSourceName())){
                        flag = true;
                        break;
                    }
                }
                if(!flag){
                    extension.put(key, itemMap.get(key));
                }
            }
            result.put("extension",extension);
            return result.toJavaObject(result, getTClass());
           // return result.toJavaObject(getTClass());
        }
        
        /**
         * 有映射规则的字段
         * @param json
         * @param attribute
         * @return
         */
        private Object mappingInternal(JSONObject json, DataAttribute attribute){
            // TODO 实现逻辑
            Object result ="";
            switch (attribute.getDataType()) {
                case STRING:
                    result = json.getString(attribute.getSourceName());
                    break;
                case INTEGER:
                    result = json.getInteger(attribute.getSourceName());
                    break;
                case LONG:
                    result = json.getLong(attribute.getSourceName());
                    break;
                case BOOLEAN:
                    result = json.getBoolean(attribute.getSourceName());
                    break;
                case DATE:
                    // TODO 考虑日期格式
                    result = json.getDate(attribute.getSourceName());
                    break;
                default:
                    result = json.get(attribute.getSourceName());
                    break;
            }
            return result;
        }
    
        private Class<T> getTClass()
        {
            if(tClass == null){
                tClass = (Class<T>)((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];
            }
            return tClass;
        }
    }
    View Code

    extend是

    Json转Map 这样就知道所有的key了 ,然后定义的规则没有的字段放入Map里

    测试

    接受实体

    public class Member {
    
        private String memberId;
    
        /** 存放对方给了 但是我们没有的字段*/
        private Map extension;
    
        private String name;
    
        private String gender;
    View Code

    转换工具类

    public class MemberConvertor extends DataConvertor<Member>{
    
    }

    补充转List

        public List<T> toInternals(String tenant, DataStrategy strategy, String jsonData) {
            JSONArray jsonArray = JSON.parseArray(jsonData);
            List<T> result = new ArrayList<>();
            for (int i = 0; i < jsonArray.size(); i++){
                JSONObject jsonObject = jsonArray.getJSONObject(i);
                result.add(toInternal(tenant,strategy,JSONObject.toJSONString(jsonObject)));
            }
            return result;
        }

    Json数组 循环

    外部实体对象

    public class SourMember {
        private String id;
        private String name;
        private String gender;
        private int age;

    分析

    age 字段我们没有,按照我们设想应该是进入map里

    id的值转换到memberI里

    测试

        public static void main(String[] args) {
            SourMember attr = new SourMember();
            attr.setGender("man");
            attr.setId("001");
            attr.setName("kebi");
            attr.setAge(123);
            String jsonData = JSONObject.toJSONString(attr);
            
            DataStrategy strategy = new DataStrategy();
            strategy.setMapping(true);
            List<DataAttribute> attributes = new ArrayList<>();
            attributes.add(createDataAttribute(AttributeDataType.STRING, "memberId", "id"));
            attributes.add(createDataAttribute(AttributeDataType.STRING, "name", "name"));
            attributes.add(createDataAttribute(AttributeDataType.STRING, "gender", "gender"));
            strategy.setAttributes(attributes);
            MemberConvertor conv = new MemberConvertor();
            Member member = conv.toInternal(strategy, jsonData);
            System.out.println(member);
        }
    View Code

    结果

    Member [memberId=001, extension={age=123}, name=kebi, gender=man]
    View Code

    策略 存储到数据库里

    DataStrategy 
    考虑 根据id查询策略的时候,如果数据很多,每一次查询数据库显得太频繁,使用redis 做缓存

    2、属性里包含对象或者集合处理办法
    添加枚举类型
    public enum AttributeDataType {
        STRING, INTEGER, LONG, DATE, BOOLEAN,CLAZZ,LISTCLAZZ;
    }
               case CLAZZ:
                    result = JSONObject.parseObject(json.getString(attribute.getSourceName()));
                    break;  
                case LISTCLAZZ:
                    result = JSON.parseArray(json.getString(attribute.getSourceName()));
                    break;
                default:

    测试

    public class SourMember {
        private String id;
        private String name;
        private String gender;
        private String birday;
        private List<Friend> friendList;
        private Car car;
    View Code

    属性里面新增了Car 和List

    引用

    DataAttribute carDataAttr = createDataAttribute(AttributeDataType.CLAZZ, "car", "car");
    DataAttribute friendDataAttr = createDataAttribute(AttributeDataType.CLAZZ, "friendList", "friendList");
          
     
  • 相关阅读:
    ESP8266 STA TCP 客户端配置并连接通信
    Modbus CRC16 校验计算函数
    自写简易版从机Modbus
    STM32CubeIDE查看内存使用情况
    WPF 样式Style
    WPF选项卡页面分离之Page调用Window类
    WPF 多个选项卡TabControl 页面分离
    STM32Cube IDE 汉字字体变小解决办法
    浮点数double相等性比较
    Ling应用
  • 原文地址:https://www.cnblogs.com/lyon91/p/9889145.html
Copyright © 2020-2023  润新知