Лучшие практики при создании пользовательских кодировщиков для официальных драйверов Go Mongo - PullRequest
0 голосов
/ 04 мая 2019

Мне было просто интересно, каковы лучшие практики в отношении создания пользовательского кодировщика для поддержки драйверов Go Mongo.Ниже приведена моя текущая реализация пользовательского обработчика для данных Binary, OID и Date, которые извлекаются из базы данных и кодируются в JSON.


var CustomRegistry = createCustomRegistry().Build()
var tBinary = reflect.TypeOf(primitive.Binary{})
var tOID = reflect.TypeOf(primitive.ObjectID{})
var tDateTime = reflect.TypeOf(primitive.DateTime(0))

func createCustomRegistry() *bsoncodec.RegistryBuilder {
    var primitiveCodecs bson.PrimitiveCodecs
    rb := bsoncodec.NewRegistryBuilder()
    bsoncodec.DefaultValueEncoders{}.RegisterDefaultEncoders(rb)
    bsoncodec.DefaultValueDecoders{}.RegisterDefaultDecoders(rb)
    rb.RegisterEncoder(tBinary, bsoncodec.ValueEncoderFunc(binaryEncodeCustomValue))
    rb.RegisterEncoder(tOID, bsoncodec.ValueEncoderFunc(objectIDEncodeValue))
    rb.RegisterEncoder(tDateTime, bsoncodec.ValueEncoderFunc(dateTimeEncodeValue))
    primitiveCodecs.RegisterPrimitiveCodecs(rb)
    return rb
}

func binaryEncodeCustomValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
    if !val.IsValid() || val.Type() != tBinary {
        return bsoncodec.ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val}
    }

    in := val.Interface().(primitive.Binary)
    out := make([]byte, base64.StdEncoding.EncodedLen(len(in.Data)))
    base64.StdEncoding.Encode(out, in.Data)
    s, err := util.BinaryToCSUUID(in.Data)
    if err != nil {
        return bsoncodec.ValueEncoderError{Name: "BinaryEncodeValue", Types: []reflect.Type{tBinary}, Received: val}
    }

    return vw.WriteString(s)
}

func objectIDEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
    if !val.IsValid() || val.Type() != tOID {
        return bsoncodec.ValueEncoderError{Name: "ObjectIDEncodeValue", Types: []reflect.Type{tOID}, Received: val}
    }
    s := val.Interface().(primitive.ObjectID).Hex()
    return vw.WriteString(s)
}

func dateTimeEncodeValue(ec bsoncodec.EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
    const jdateFormat = "2006-01-02T15:04:05.999Z"
    if !val.IsValid() || val.Type() != tDateTime {
        return bsoncodec.ValueEncoderError{Name: "DateTimeEncodeValue", Types: []reflect.Type{tDateTime}, Received: val}
    }

    ints := val.Int()
    t := time.Unix(0, ints*1000000)

    return vw.WriteString(t.Format(jdateFormat))
}

Я вызываю приведенный выше код, используя следующую функцию:

data, writeErr := bson.MarshalExtJSONWithRegistry(CustomRegistry, result, false, false)

Я не нашел много документации о том, как это должно быть обработано.Есть ли лучший способ сделать это?

...