设为首页 加入收藏

TOP

做一次面向对象的体操:将JSON字符串转换为嵌套对象的一种方法(六)
2018-09-04 20:46:40 】 浏览:591
Tags:一次 面向 对象 体操 JSON 字符串 转换 方法
bizObjects.add(map2Bean(mapForKey, bizObjects.getObjectClass())); } ); return this; } public List<ItemCore> buildFinalList() { Map<String, List<ItemCore>> itemCores = objMapping.get("item_core").getObjects(); List<ItemCore> finalItemCoreList = new ArrayList<>(); itemCores.forEach( (itemCoreId, itemCoreList) -> { ItemCore itemCore = itemCoreList.get(0); itemCore.setItem((Item) objMapping.get("item").getSingle(itemCoreId)); itemCore.setItemPrice((ItemPrice) objMapping.get("item_price").getSingle(itemCoreId)); itemCore.setItemPriceChangeLogs(objMapping.get("item_price_change_log").get(itemCoreId)); finalItemCoreList.add(itemCore); } ); return finalItemCoreList; } }

BizObjects.java

package zzz.study.algorithm.object;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;

public class BizObjects<T, K> {

  private Class<T> cls;
  private Map<K, List<T>> map;
  private Function<T, K> keyFunc;

  public BizObjects(Class<T> cls, Map<K,List<T>> map, Function<T,K> keyFunc) {
    this.cls = cls;
    this.map = (map != null ? map : new HashMap<>());
    this.keyFunc = keyFunc;
  }

  public void add(T t) {
    K key = keyFunc.apply(t);
    List<T> objs = map.getOrDefault(key, new ArrayList<>());
    objs.add(t);
    map.put(key, objs);
  }

  public Class<T> getObjectClass() {
    return cls;
  }

  public List<T> get(K key) {
    return map.get(key);
  }

  public T getSingle(K key) {
    return (map != null && map.containsKey(key) && map.get(key).size() > 0) ? map.get(key).get(0) : null;
  }

  public Map<K, List<T>> getObjects() {
    return Collections.unmodifiableMap(map);
  }

}

新的实现的主要特点在于:

  • 去掉了条件语句;
  • 将转换为嵌套对象的重要配置与逻辑都集中到 objMapping ;
  • 更加对象化的思维。

美中不足的是,大量使用了泛型来提高通用性,同时也牺牲了运行时安全的好处(需要强制类型转换)。 后半段关联对象,还是不够配置化,暂时没想到更好的方法。

为什么 BizObjects 里要用 Map 而不用 List 来表示多个对象呢 ? 因为后面需要根据 itemCoreId 来关联相应对象。如果用 List , 后续还要一个单独的 buildObjMap 操作。这里添加的时候就构建 Map ,将行为集中于 BizObjects 内部管理, 为后续配置化地关联对象留下一个空间。

一个小坑

运行结果会发现,转换后的 item 对象的属性 sId, gId 的值为 null 。纳尼 ? 这是怎么回事呢?

单步调试,运行后,会发现在 BeanUtilsBean.java 932 行有这样一行代码(用的是 commons-beanutils 的 1.9.3 版本):

PropertyDescriptor descriptor = null;
            try {
                descriptor =
                    getPropertyUtils().getPropertyDescriptor(target, name);
                if (descriptor == null) {
                    return; // Skip this property setter
                }
            } catch (final NoSuchMethodException e) {
                return; // Skip this property setter
            }

当 name = “gId” 时,会获取不到 descriptor 直接返回。 为什么获取不到呢,因为 Item propertyDescriptors 缓存里的 key是 GId ,而不是 gId !

为什么 itemPropertyDescriptors 里的 key 是 GId 呢? 进一步跟踪到 propertyDescriptors 的生成,在 Introspector.getTargetPropertyInfo 方法中,是根据属性的 getter/setter 方法来生成 propertyDescriptor 的 name 的。 最终定位的代码是 Introspector.decapitalize 方法:

public static String decapitalize(String name) {
        if (name == null || name.length() == 0) {
            return name;
        }
        if (name.length() > 1 && Character.isUpperCase(name.charAt(1)) &&
                        Character.isUpperCase(name.charAt(0))){
            return name;
        }
        char chars[] = name.toCharArray();
        chars[0]
首页 上一页 3 4 5 6 下一页 尾页 6/6/6
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇SpringBoot | 第十五章:基于Post.. 下一篇Map大家族的那点事儿(2) :Abstra..

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目