package extensions
import (
"fmt"
"reflect"
"slices"
"github.com/apache/arrow-go/v18/arrow"
"github.com/apache/arrow-go/v18/arrow/array"
"github.com/apache/arrow-go/v18/internal/json"
"github.com/apache/arrow-go/v18/parquet/schema"
)
var jsonSupportedStorageTypes = []arrow .DataType {
arrow .BinaryTypes .String ,
arrow .BinaryTypes .LargeString ,
arrow .BinaryTypes .StringView ,
}
type JSONType struct {
arrow .ExtensionBase
}
func (b *JSONType ) ParquetLogicalType () schema .LogicalType {
return schema .JSONLogicalType {}
}
func NewJSONType (storageType arrow .DataType ) (*JSONType , error ) {
if !slices .Contains (jsonSupportedStorageTypes , storageType ) {
return nil , fmt .Errorf ("unsupported storage type for JSON extension type: %s" , storageType )
}
return &JSONType {ExtensionBase : arrow .ExtensionBase {Storage : storageType }}, nil
}
func (b *JSONType ) ArrayType () reflect .Type { return reflect .TypeOf (JSONArray {}) }
func (b *JSONType ) Deserialize (storageType arrow .DataType , data string ) (arrow .ExtensionType , error ) {
if data != "" && data != "{}" {
return nil , fmt .Errorf ("serialized metadata for JSON extension type must be '' or '{}', found: %s" , data )
}
return NewJSONType (storageType )
}
func (b *JSONType ) ExtensionEquals (other arrow .ExtensionType ) bool {
return b .ExtensionName () == other .ExtensionName () && arrow .TypeEqual (b .Storage , other .StorageType ())
}
func (b *JSONType ) ExtensionName () string { return "arrow.json" }
func (b *JSONType ) Serialize () string { return "" }
func (b *JSONType ) String () string {
return fmt .Sprintf ("extension<%s[storage_type=%s]>" , b .ExtensionName (), b .Storage )
}
type JSONArray struct {
array .ExtensionArrayBase
}
func (a *JSONArray ) String () string {
b , err := a .MarshalJSON ()
if err != nil {
panic (fmt .Sprintf ("failed marshal JSONArray: %s" , err ))
}
return string (b )
}
func (a *JSONArray ) Value (i int ) any {
val := a .ValueBytes (i )
var res any
if err := json .Unmarshal (val , &res ); err != nil {
panic (err )
}
return res
}
func (a *JSONArray ) ValueStr (i int ) string {
return string (a .ValueBytes (i ))
}
func (a *JSONArray ) ValueBytes (i int ) []byte {
val := a .ValueJSON (i )
b , err := val .MarshalJSON ()
if err != nil {
panic (err )
}
return b
}
func (a *JSONArray ) ValueJSON (i int ) json .RawMessage {
var val json .RawMessage
if a .IsValid (i ) {
val = json .RawMessage (a .Storage ().(array .StringLike ).Value (i ))
}
return val
}
func (a *JSONArray ) MarshalJSON () ([]byte , error ) {
values := make ([]json .RawMessage , a .Len ())
for i := 0 ; i < a .Len (); i ++ {
values [i ] = a .ValueJSON (i )
}
return json .Marshal (values )
}
func (a *JSONArray ) GetOneForMarshal (i int ) interface {} {
return a .ValueJSON (i )
}
var (
_ arrow .ExtensionType = (*JSONType )(nil )
_ array .ExtensionArray = (*JSONArray )(nil )
)
The pages are generated with Golds v0.8.2 . (GOOS=linux GOARCH=amd64)
Golds is a Go 101 project developed by Tapir Liu .
PR and bug reports are welcome and can be submitted to the issue list .
Please follow @zigo_101 (reachable from the left QR code) to get the latest news of Golds .