private Object serializeStruct(StructTypeInfo typeInfo, StructObjectInspector ssoi, Object o, Schema schema) throws AvroSerdeException {
    int size = schema.getFields().size();
    List<? extends StructField> allStructFieldRefs = ssoi.getAllStructFieldRefs();
    List<Object> structFieldsDataAsList = ssoi.getStructFieldsDataAsList(o);
    GenericData.Record record = new GenericData.Record(schema);
    List<TypeInfo> allStructFieldTypeInfos = typeInfo.getAllStructFieldTypeInfos();

    for(int i  = 0; i < size; i++) {
      Field field = schema.getFields().get(i);
      TypeInfo colTypeInfo = allStructFieldTypeInfos.get(i);
      StructField structFieldRef = allStructFieldRefs.get(i);
      Object structFieldData = structFieldsDataAsList.get(i);
      ObjectInspector fieldOI = structFieldRef.getFieldObjectInspector();

      Object val = serialize(colTypeInfo, fieldOI, structFieldData, field.schema());
      record.put(field.name(), val);
    }
    return record;
  }
private cache to avoid lots of EnumSymbol creation while serializing.
 Two levels because the enum symbol is specific to a schema.
 Object because we want to avoid the overhead of repeated toString calls while maintaining compatibility.
 Provided there are few enum types per record, and few symbols per enum, memory use should be moderate.
 eg 20 types with 50 symbols each as length-10 Strings should be on the order of 100KB per AvroSerializer.
serde/src/java/org/apache/hadoop/hive/serde2/avro/AvroSerializer.java