public static Object copyToStandardObject(
      Object o, ObjectInspector oi, ObjectInspectorCopyOption objectInspectorOption) {
    if (o == null) {
      return null;
    }

    Object result = null;
    switch (oi.getCategory()) {
    case PRIMITIVE: {
      PrimitiveObjectInspector loi = (PrimitiveObjectInspector) oi;
      if (objectInspectorOption == ObjectInspectorCopyOption.DEFAULT) {
        objectInspectorOption = loi.preferWritable() ?
            ObjectInspectorCopyOption.WRITABLE : ObjectInspectorCopyOption.JAVA;
      }
      switch (objectInspectorOption) {
      case JAVA:
        result = loi.getPrimitiveJavaObject(o);
        if (loi.getPrimitiveCategory() == PrimitiveObjectInspector.PrimitiveCategory.TIMESTAMP) {
          result = PrimitiveObjectInspectorFactory.javaTimestampObjectInspector.copyObject(result);
        } else if (loi.getPrimitiveCategory() ==
            PrimitiveObjectInspector.PrimitiveCategory.TIMESTAMPLOCALTZ) {
          result = PrimitiveObjectInspectorFactory.javaTimestampTZObjectInspector.
              copyObject(result);
        }
        break;
      case WRITABLE:
        result = loi.getPrimitiveWritableObject(loi.copyObject(o));
        break;
      }
      break;
    }
    case LIST: {
      ListObjectInspector loi = (ListObjectInspector) oi;
      int length = loi.getListLength(o);
      ArrayList<Object> list = new ArrayList<Object>(length);
      for (int i = 0; i < length; i++) {
        list.add(copyToStandardObject(loi.getListElement(o, i), loi
            .getListElementObjectInspector(), objectInspectorOption));
      }
      result = list;
      break;
    }
    case MAP: {
      MapObjectInspector moi = (MapObjectInspector) oi;
      Map<Object, Object> map = new LinkedHashMap<Object, Object>();
      Map<? extends Object, ? extends Object> omap = moi.getMap(o);
      for (Map.Entry<? extends Object, ? extends Object> entry : omap
          .entrySet()) {
        map.put(copyToStandardObject(entry.getKey(), moi
            .getMapKeyObjectInspector(), objectInspectorOption),
            copyToStandardObject(entry.getValue(), moi
            .getMapValueObjectInspector(), objectInspectorOption));
      }
      result = map;
      break;
    }
    case STRUCT: {
      StructObjectInspector soi = (StructObjectInspector) oi;
      List<? extends StructField> fields = soi.getAllStructFieldRefs();
      ArrayList<Object> struct = new ArrayList<Object>(fields.size());
      for (StructField f : fields) {
        struct.add(copyToStandardObject(soi.getStructFieldData(o, f), f
            .getFieldObjectInspector(), objectInspectorOption));
      }
      result = struct;
      break;
    }
    case UNION: {
      UnionObjectInspector uoi = (UnionObjectInspector)oi;
      List<ObjectInspector> objectInspectors = uoi.getObjectInspectors();
      byte tag = uoi.getTag(o);
      Object object = copyToStandardObject(
              uoi.getField(o),
              objectInspectors.get(tag),
              objectInspectorOption);
      result = new StandardUnionObjectInspector.StandardUnion(tag, object);
      break;
    }
    default: {
      throw new RuntimeException("Unknown ObjectInspector category!");
    }
    }
    return result;
  }
Returns a deep copy of the Object o that can be scanned by a
StandardObjectInspector returned by getStandardObjectInspector(oi).
serde/src/java/org/apache/hadoop/hive/serde2/objectinspector/ObjectInspectorUtils.java