func()

in arrow/internal/arrjson/arrjson.go [247:490]


func (f *FieldWrapper) UnmarshalJSON(data []byte) error {
	if err := json.Unmarshal(data, &f.Field); err != nil {
		return err
	}

	tmp := nameJSON{}
	if err := json.Unmarshal(f.Type, &tmp); err != nil {
		return err
	}

	switch tmp.Name {
	case "null":
		f.arrowType = arrow.Null
	case "bool":
		f.arrowType = arrow.FixedWidthTypes.Boolean
	case "int":
		t := bitWidthJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		switch t.Signed {
		case true:
			switch t.BitWidth {
			case 8:
				f.arrowType = arrow.PrimitiveTypes.Int8
			case 16:
				f.arrowType = arrow.PrimitiveTypes.Int16
			case 32:
				f.arrowType = arrow.PrimitiveTypes.Int32
			case 64:
				f.arrowType = arrow.PrimitiveTypes.Int64
			}
		default:
			switch t.BitWidth {
			case 8:
				f.arrowType = arrow.PrimitiveTypes.Uint8
			case 16:
				f.arrowType = arrow.PrimitiveTypes.Uint16
			case 32:
				f.arrowType = arrow.PrimitiveTypes.Uint32
			case 64:
				f.arrowType = arrow.PrimitiveTypes.Uint64
			}
		}
	case "floatingpoint":
		t := floatJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		switch t.Precision {
		case "HALF":
			f.arrowType = arrow.FixedWidthTypes.Float16
		case "SINGLE":
			f.arrowType = arrow.PrimitiveTypes.Float32
		case "DOUBLE":
			f.arrowType = arrow.PrimitiveTypes.Float64
		}
	case "binary":
		f.arrowType = arrow.BinaryTypes.Binary
	case "utf8":
		f.arrowType = arrow.BinaryTypes.String
	case "date":
		t := unitZoneJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		switch t.Unit {
		case "DAY":
			f.arrowType = arrow.FixedWidthTypes.Date32
		case "MILLISECOND":
			f.arrowType = arrow.FixedWidthTypes.Date64
		}
	case "time":
		t := bitWidthJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		switch t.BitWidth {
		case 32:
			switch t.Unit {
			case "SECOND":
				f.arrowType = arrow.FixedWidthTypes.Time32s
			case "MILLISECOND":
				f.arrowType = arrow.FixedWidthTypes.Time32ms
			}
		case 64:
			switch t.Unit {
			case "MICROSECOND":
				f.arrowType = arrow.FixedWidthTypes.Time64us
			case "NANOSECOND":
				f.arrowType = arrow.FixedWidthTypes.Time64ns
			}
		}
	case "timestamp":
		t := unitZoneJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		f.arrowType = &arrow.TimestampType{TimeZone: t.TimeZone}
		switch t.Unit {
		case "SECOND":
			f.arrowType.(*arrow.TimestampType).Unit = arrow.Second
		case "MILLISECOND":
			f.arrowType.(*arrow.TimestampType).Unit = arrow.Millisecond
		case "MICROSECOND":
			f.arrowType.(*arrow.TimestampType).Unit = arrow.Microsecond
		case "NANOSECOND":
			f.arrowType.(*arrow.TimestampType).Unit = arrow.Nanosecond
		}
	case "list":
		f.arrowType = arrow.ListOfField(arrow.Field{
			Name:     f.Children[0].Name,
			Type:     f.Children[0].arrowType,
			Metadata: f.Children[0].arrowMeta,
			Nullable: f.Children[0].Nullable,
		})
	case "map":
		t := mapJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		pairType := f.Children[0].arrowType
		f.arrowType = arrow.MapOf(pairType.(*arrow.StructType).Field(0).Type, pairType.(*arrow.StructType).Field(1).Type)
		f.arrowType.(*arrow.MapType).KeysSorted = t.KeysSorted
	case "struct":
		f.arrowType = arrow.StructOf(fieldsFromJSON(f.Children)...)
	case "fixedsizebinary":
		t := byteWidthJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		f.arrowType = &arrow.FixedSizeBinaryType{ByteWidth: t.ByteWidth}
	case "fixedsizelist":
		t := listSizeJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		f.arrowType = arrow.FixedSizeListOfField(t.ListSize, arrow.Field{
			Name:     f.Children[0].Name,
			Type:     f.Children[0].arrowType,
			Metadata: f.Children[0].arrowMeta,
			Nullable: f.Children[0].Nullable,
		})
	case "interval":
		t := unitZoneJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		switch t.Unit {
		case "YEAR_MONTH":
			f.arrowType = arrow.FixedWidthTypes.MonthInterval
		case "DAY_TIME":
			f.arrowType = arrow.FixedWidthTypes.DayTimeInterval
		case "MONTH_DAY_NANO":
			f.arrowType = arrow.FixedWidthTypes.MonthDayNanoInterval
		}
	case "duration":
		t := unitZoneJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		switch t.Unit {
		case "SECOND":
			f.arrowType = arrow.FixedWidthTypes.Duration_s
		case "MILLISECOND":
			f.arrowType = arrow.FixedWidthTypes.Duration_ms
		case "MICROSECOND":
			f.arrowType = arrow.FixedWidthTypes.Duration_us
		case "NANOSECOND":
			f.arrowType = arrow.FixedWidthTypes.Duration_ns
		}
	case "decimal":
		t := decimalJSON{}
		if err := json.Unmarshal(f.Type, &t); err != nil {
			return err
		}
		f.arrowType = &arrow.Decimal128Type{Precision: int32(t.Precision), Scale: int32(t.Scale)}
	}

	if f.arrowType == nil {
		return xerrors.Errorf("unhandled type unmarshalling from json: %s", tmp.Name)
	}

	var err error
	if len(f.Metadata) > 0 { // unmarshal the key/value metadata pairs
		var (
			mdkeys         = make([]string, 0, len(f.Metadata))
			mdvals         = make([]string, 0, len(f.Metadata))
			extKeyIdx  int = -1
			extDataIdx int = -1
		)

		for i, kv := range f.Metadata {
			switch kv.Key {
			case ipc.ExtensionTypeKeyName:
				extKeyIdx = i
			case ipc.ExtensionMetadataKeyName:
				extDataIdx = i
			}
			mdkeys = append(mdkeys, kv.Key)
			mdvals = append(mdvals, kv.Value)
		}

		if extKeyIdx == -1 { // no extension metadata just create the metadata
			f.arrowMeta = arrow.NewMetadata(mdkeys, mdvals)
			return nil
		}

		extType := arrow.GetExtensionType(mdvals[extKeyIdx])
		if extType == nil { // unregistered extension type, just keep the metadata
			f.arrowMeta = arrow.NewMetadata(mdkeys, mdvals)
			return nil
		}

		var extData string
		if extDataIdx > -1 {
			extData = mdvals[extDataIdx]
			// if both extension type and extension type metadata exist
			// filter out both keys
			newkeys := make([]string, 0, len(mdkeys)-2)
			newvals := make([]string, 0, len(mdvals)-2)
			for i := range mdkeys {
				if i != extKeyIdx && i != extDataIdx {
					newkeys = append(newkeys, mdkeys[i])
					newvals = append(newvals, mdvals[i])
				}
			}
			mdkeys = newkeys
			mdvals = newvals
		} else {
			// if only extension type key is present, we can simplify filtering it out
			mdkeys = append(mdkeys[:extKeyIdx], mdkeys[extKeyIdx+1:]...)
			mdvals = append(mdvals[:extKeyIdx], mdvals[extKeyIdx+1:]...)
		}

		if f.arrowType, err = extType.Deserialize(f.arrowType, extData); err != nil {
			return err
		}

		f.arrowMeta = arrow.NewMetadata(mdkeys, mdvals)
	}

	return err
}