static Object convertValue(Object val, ObjectInspector oi) {
    if (val == null) {
      return null;
    }

    Object convertedVal = null;
    ObjectInspector.Category oiCategory = oi.getCategory();
    switch (oiCategory) {
    case PRIMITIVE:
      convertedVal = convertPrimitive(val, (PrimitiveObjectInspector) oi);
      break;
    case LIST:
      ListObjectInspector loi = (ListObjectInspector) oi;
      int listSize = loi.getListLength(val);
      // Per ListObjectInpsector.getListLength(), -1 length means null list.
      if (listSize < 0) {
        return null;
      }
      List<Object> convertedList = new ArrayList<Object>(listSize);
      ObjectInspector listElementOI = loi.getListElementObjectInspector();
      for (int idx = 0; idx < listSize; ++idx) {
        convertedList.add(convertValue(loi.getListElement(val, idx), listElementOI));
      }
      convertedVal = convertedList;
      break;
    case MAP:
      MapObjectInspector moi = (MapObjectInspector) oi;
      int mapSize = moi.getMapSize(val);
      // Per MapObjectInpsector.getMapSize(), -1 length means null map.
      if (mapSize < 0) {
        return null;
      }
      Map<Object, Object> convertedMap = new LinkedHashMap<Object, Object>(mapSize);
      ObjectInspector mapKeyOI = moi.getMapKeyObjectInspector();
      ObjectInspector mapValOI = moi.getMapValueObjectInspector();
      Map<?, ?> mapCol = moi.getMap(val);
      for (Object mapKey : mapCol.keySet()) {
        Object convertedMapKey = convertValue(mapKey, mapKeyOI);
        Object convertedMapVal = convertValue(mapCol.get(mapKey), mapValOI);
        convertedMap.put(convertedMapKey,  convertedMapVal);
      }
      convertedVal = convertedMap;
      break;
    case STRUCT:
      StructObjectInspector soi = (StructObjectInspector) oi;
      List<Object> convertedRow = new ArrayList<Object>();
      for (StructField structField : soi.getAllStructFieldRefs()) {
        Object convertedFieldValue = convertValue(
            soi.getStructFieldData(val, structField),
            structField.getFieldObjectInspector());
        convertedRow.add(convertedFieldValue);
      }
      convertedVal = convertedRow;
      break;
    default:
      throw new IllegalArgumentException("Cannot convert type " + oiCategory);
    }

    return convertedVal;
  }
Row-based record reader for LLAP.
llap-client/src/java/org/apache/hadoop/hive/llap/LlapRowRecordReader.java