public Object randomWritable(TypeInfo typeInfo, ObjectInspector objectInspector, boolean allowNull) {
    switch (typeInfo.getCategory()) {
    case PRIMITIVE:
      {
        final Object object = randomPrimitiveObject(r, (PrimitiveTypeInfo) typeInfo);
        return getWritablePrimitiveObject((PrimitiveTypeInfo) typeInfo, objectInspector, object);
      }
    case LIST:
      {
        if (allowNull && r.nextInt(20) == 0) {
          return null;
        }
        // Always generate a list with at least 1 value?
        final int elementCount = 1 + r.nextInt(100);
        final StandardListObjectInspector listObjectInspector =
            (StandardListObjectInspector) objectInspector;
        final ObjectInspector elementObjectInspector =
            listObjectInspector.getListElementObjectInspector();
        final TypeInfo elementTypeInfo =
            TypeInfoUtils.getTypeInfoFromObjectInspector(
                elementObjectInspector);
        boolean isStringFamily = false;
        PrimitiveCategory primitiveCategory = null;
        if (elementTypeInfo.getCategory() == Category.PRIMITIVE) {
          primitiveCategory = ((PrimitiveTypeInfo) elementTypeInfo).getPrimitiveCategory();
          if (primitiveCategory == PrimitiveCategory.STRING ||
              primitiveCategory == PrimitiveCategory.BINARY ||
              primitiveCategory == PrimitiveCategory.CHAR ||
              primitiveCategory == PrimitiveCategory.VARCHAR) {
            isStringFamily = true;
          }
        }
        final Object listObj = listObjectInspector.create(elementCount);
        for (int i = 0; i < elementCount; i++) {
          final Object ele = randomWritable(elementTypeInfo, elementObjectInspector, allowNull);
          // UNDONE: For now, a 1-element list with a null element is a null list...
          if (ele == null && elementCount == 1) {
            return null;
          }
          if (isStringFamily && elementCount == 1) {
            switch (primitiveCategory) {
            case STRING:
              if (((Text) ele).getLength() == 0) {
                return null;
              }
              break;
            case BINARY:
              if (((BytesWritable) ele).getLength() == 0) {
                return null;
              }
              break;
            case CHAR:
              if (((HiveCharWritable) ele).getHiveChar().getStrippedValue().isEmpty()) {
                return null;
              }
              break;
            case VARCHAR:
              if (((HiveVarcharWritable) ele).getHiveVarchar().getValue().isEmpty()) {
                return null;
              }
              break;
            default:
              throw new RuntimeException("Unexpected primitive category " + primitiveCategory);
            }
          }
          listObjectInspector.set(listObj, i, ele);
        }
        return listObj;
      }
    case MAP:
      {
        if (allowNull && r.nextInt(20) == 0) {
          return null;
        }
        final int keyPairCount = r.nextInt(100);
        final StandardMapObjectInspector mapObjectInspector =
            (StandardMapObjectInspector) objectInspector;
        final ObjectInspector keyObjectInspector =
            mapObjectInspector.getMapKeyObjectInspector();
        final TypeInfo keyTypeInfo =
            TypeInfoUtils.getTypeInfoFromObjectInspector(
                keyObjectInspector);
        final ObjectInspector valueObjectInspector =
            mapObjectInspector.getMapValueObjectInspector();
        final TypeInfo valueTypeInfo =
            TypeInfoUtils.getTypeInfoFromObjectInspector(
                valueObjectInspector);
        final Object mapObj = mapObjectInspector.create();
        for (int i = 0; i < keyPairCount; i++) {
          final Object key = randomWritable(keyTypeInfo, keyObjectInspector);
          final Object value = randomWritable(valueTypeInfo, valueObjectInspector);
          mapObjectInspector.put(mapObj, key, value);
        }
        return mapObj;
      }
    case STRUCT:
      {
        if (allowNull && r.nextInt(20) == 0) {
          return null;
        }
        final StandardStructObjectInspector structObjectInspector =
            (StandardStructObjectInspector) objectInspector;
        final List<? extends StructField> fieldRefsList = structObjectInspector.getAllStructFieldRefs();
        final int fieldCount = fieldRefsList.size();
        final Object structObj = structObjectInspector.create();
        for (int i = 0; i < fieldCount; i++) {
          final StructField fieldRef = fieldRefsList.get(i);
          final ObjectInspector fieldObjectInspector =
               fieldRef.getFieldObjectInspector();
          final TypeInfo fieldTypeInfo =
              TypeInfoUtils.getTypeInfoFromObjectInspector(
                  fieldObjectInspector);
          final Object fieldObj = randomWritable(fieldTypeInfo, fieldObjectInspector);
          structObjectInspector.setStructFieldData(structObj, fieldRef, fieldObj);
        }
        return structObj;
      }
    case UNION:
      {
        final StandardUnionObjectInspector unionObjectInspector =
            (StandardUnionObjectInspector) objectInspector;
        final List<ObjectInspector> objectInspectorList = unionObjectInspector.getObjectInspectors();
        final int unionCount = objectInspectorList.size();
        final byte tag = (byte) r.nextInt(unionCount);
        final ObjectInspector fieldObjectInspector =
            objectInspectorList.get(tag);
        final TypeInfo fieldTypeInfo =
            TypeInfoUtils.getTypeInfoFromObjectInspector(
                fieldObjectInspector);
        final Object fieldObj = randomWritable(fieldTypeInfo, fieldObjectInspector, false);
        if (fieldObj == null) {
          throw new RuntimeException();
        }
        return new StandardUnion(tag, fieldObj);
      }
    default:
      throw new RuntimeException("Unexpected category " + typeInfo.getCategory());
    }
  }
Generate object inspector and random row object[].
serde/src/test/org/apache/hadoop/hive/serde2/SerdeRandomRowSource.java