美文网首页
【平台化引擎-2】— 参数扁平与结构化操作

【平台化引擎-2】— 参数扁平与结构化操作

作者: 小胖学编程 | 来源:发表于2024-02-04 18:34 被阅读0次

背景

如果提供一个平台化的页面供用户操作,如果用户想在页面上操作入参,需要将复杂的对象扁平化展示,以便用户操作。

页面操作流程.png

用户想在页面上操作数据流中的参数,是需要拿到结构化参数中的字段,为了便于用户操作,需要支持扁平化的操作

参数扁平化

原始数据:

{
    "address":[
        {
            "area":"白帝小区",
            "city":"洛阳",
            "phone":"13617172122",
            "province":"河南"
        },
        {
            "area":"邯郸小区",
            "city":"邯郸",
            "phone":"19917172122",
            "province":"河北"
        },
        {
            "area":"德州小区",
            "city":"德州",
            "phone":"18817172122",
            "province":"山东"
        }
    ],
    "balance":10.11,
    "birthday":{
        "day":"30",
        "mon":"11",
        "year":"2020"
    },
    "name":"小白",
    "uid":1001
}

结构化schema:

{
    "address":[
        {
            "area":"String",
            "city":"String",
            "phone":"String",
            "province":"String"
        }
    ],
    "balance":"BigDecimal",
    "birthday":{
        "day":"String",
        "mon":"String",
        "year":"String"
    },
    "name":"String",
    "uid":"Integer"
}

扁平化schema:

{
    "address":"LIST",
    "address.0":"MAP",
    "address.0.area":"String",
    "address.0.city":"String",
    "address.0.phone":"String",
    "address.0.province":"String",
    "balance":"BigDecimal",
    "birthday":"MAP",
    "birthday.day":"String",
    "birthday.mon":"String",
    "birthday.year":"String",
    "name":"String",
    "uid":"Integer"
}

如上图所示。我们可以拿到扁平化的schema结构后,那么在页面上可以输入address.0.area,就可以获取到Map中的对于的value值(作为Context上下文,执行脚本)。

代码实现

数据准备

public interface SourceParam {
    /**
     * 获取参数元数据
     */
    Map<String, Object> getParamMeta();
}
public class MockSourceParam implements SourceParam {
    @Override
    public Map<String, Object> getParamMeta() {
        //原数据
        UserInfo userInfo = new UserInfo();
        userInfo.setUid(1001L);
        userInfo.setName("小白");
        userInfo.setBalance(10.11);
        Birthday birthday = new Birthday();
        birthday.setYear("2020");
        birthday.setMon("11");
        birthday.setDay("30");
        userInfo.setBirthday(birthday);

        List<Address> addressList = Lists.newArrayList();
        addressList.add(Address.builder().province("河南").city("洛阳").area("白帝小区").phone("13617172122").build());
        addressList.add(Address.builder().province("河北").city("邯郸").area("邯郸小区").phone("19917172122").build());
        addressList.add(Address.builder().province("山东").city("德州").area("德州小区").phone("18817172122").build());

        userInfo.setAddress(addressList);
        System.out.println(JSON.toJSONString(userInfo));

        return JSON.parseObject(JSON.toJSONString(userInfo), Map.class);
    }

    @Data
    public static class UserInfo {

        private Long uid;

        private String name;

        private Birthday birthday;

        private double balance;

        private List<Address> address;

    }

    @Data
    public static class Birthday {
        private String year;
        private String mon;
        private String day;
    }

    @Data
    @Builder
    @NoArgsConstructor
    @AllArgsConstructor
    public static class Address {
        private String province;
        private String city;
        private String area;
        private String phone;
    }
}

工具方案:


import com.google.common.collect.Maps;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.StringUtils;

import java.util.*;
import java.util.Map.Entry;

public class ParamHelper {
    /**
     * json的嵌套格式化
     */
    public static Map<String, Object> jsonSchema(Map<String, Object> data) {
        Map<String, Object> result = Maps.newHashMap();
        if (MapUtils.isEmpty(data)) {
            return result;
        }
        data.forEach((k, v) -> {
            result.put(k, v.getClass().getSimpleName());
            //如果Map
            if (v instanceof Map) {
                result.put(k, jsonSchema((Map<String, Object>) v));
                return;
            }

            if (v instanceof Collection) {
                Collection t = (Collection) v;
                Iterator iterator = t.iterator();
                Collection c1 = new ArrayList<>();
                if (iterator.hasNext()) {
                    Object o = iterator.next();
                    if (o instanceof Map) {
                        c1.add(jsonSchema((Map<String, Object>) o));
                    } else {
                        c1.add(o.getClass().getSimpleName());
                    }
                }
                result.put(k, c1);
            }
        });
        return result;
    }

    /**
     * 写入扁平化的数据
     */
    public static Map<String, Object> putFold(Map<String, Object> data) {
        Map<String, Object> result = Maps.newHashMap();
        if (MapUtils.isEmpty(data)) {
            return result;
        }
        data.forEach((k, v) -> {
            String[] splitKey = k.split("\\.");
            int index = 0;
            Map<String, Object> indexMap = result;

            while (index < splitKey.length - 1) {
                String subKey = splitKey[index];
                indexMap = foldGetFromMap(indexMap, subKey);
                index++;
            }

            indexMap.put(splitKey[index], v);
        });
        return convertDataArray(result);
    }

    public static Map<String, Object> jsonSchemaForUnfold(Map<String, Object> data) {
        Map<String, String> unfoldData = jsonSchemaForUnfold("", data);
        Map<String, Object> res = Maps.newHashMap();

        for (Entry<String, String> entry : unfoldData.entrySet()) {
            String key = entry.getKey();
            String fieldType = entry.getValue();
            res.put(key, fieldType);
        }

        return res;
    }

    public static Map<String, String> jsonSchemaForUnfold(String prefix, Map<String, Object> data) {
        Map<String, String> result = Maps.newHashMap();
        if (MapUtils.isEmpty(data)) {
            return result;
        }
        data.forEach((k, v) -> {
            String unfoldKey;
            if (StringUtils.isNotBlank(prefix)) {
                unfoldKey = prefix + "." + k;
            } else {
                unfoldKey = k;
            }

            if (v instanceof Map) {
                result.put(unfoldKey, "MAP");
                result.putAll(jsonSchemaForUnfold(unfoldKey, (Map<String, Object>) v));
                return;
            }
            if (v instanceof Collection) {
                result.put(unfoldKey, "LIST");

                result.putAll(jsonSchemaForUnfold(unfoldKey, convertToMap((Collection) v)));
                return;
            }
            result.put(unfoldKey, v.getClass().getSimpleName());
        });
        return result;
    }
    private static Map<String, Object> convertToMap(Collection<?> collection) {
        Map<String, Object> result = Maps.newHashMap();
        if (CollectionUtils.isEmpty(collection)) {
            return result;
        }
        Iterator<?> iterator = collection.iterator();
        result.put(String.valueOf(0), iterator.next());
        return result;

    }
    private static Map<String, Object> foldGetFromMap(Map<String, Object> map, String key) {
        Object subNode = map.get(key);
        if (Objects.nonNull(subNode) && subNode instanceof Map) {
            return (Map<String, Object>) subNode;
        }
        Map<String, Object> result = Maps.newHashMap();
        map.put(key, result);
        return result;
    }

    private static Map<String, Object> convertDataArray(Map<String, Object> map) {
        Map<String, Object> result = Maps.newHashMap();
        if (MapUtils.isEmpty(map)) {
            return map;
        }
        for (Entry<String, Object> entry : map.entrySet()) {
            String k = entry.getKey();
            Object v = entry.getValue();
            if (!(v instanceof Map)) {
                result.put(k, v);
                continue;
            }
            Map<String, Object> valueMap = convertDataArray((Map<String, Object>) v);
            if (valueMap.keySet().stream().allMatch(StringUtils::isNumeric)) {
                result.put(k, valueMap.values());
                continue;
            }
            result.put(k, valueMap);
        }
        return result;
    }
}

工具类实现:

public class Test {
    public static void main(String[] args) {
        SourceParam mockSourceParam = new MockSourceParam();
        Map<String, Object> paramMeta = mockSourceParam.getParamMeta();
        //获取到json串schema结构
        System.out.println(JSON.toJSON(ParamHelper.jsonSchema(paramMeta)));
        //获取到扁平的json的schema结构
        System.out.println(JSON.toJSON(ParamHelper.jsonSchemaForUnfold(paramMeta)));
        //存储扁平化的数据
        Map<String, Object> hashMap = new HashMap<>();
        hashMap.put("userInfo.uid", 1);
        hashMap.put("userInfo.name", "tom");
        Map<String, Object> stringObjectMap = putFold(hashMap);
        System.out.println(JSON.toJSON(stringObjectMap));
    }
}

相关文章

网友评论

      本文标题:【平台化引擎-2】— 参数扁平与结构化操作

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