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");
      
 
原文地址:https://www.cnblogs.com/lyon91/p/9889145.html