dri8163 2019-05-03 23:57
浏览 32

为Go Mongo Official驱动程序创建自定义编码器时的最佳做法

I was just wondering what the best practices were in regards to handling the creation of custom encoder for the support Go Mongo drivers. The following is my current implementation of a custom handler for Binary, OID and Date data that is retrieved from the database and encoded to 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))
}

I call the above code using the following function:

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

I did not find much documentation on how this should be handled. Is there a better method to do this?

  • 写回答

0条回答 默认 最新

    报告相同问题?

    悬赏问题

    • ¥100 set_link_state
    • ¥15 虚幻5 UE美术毛发渲染
    • ¥15 CVRP 图论 物流运输优化
    • ¥15 Tableau online 嵌入ppt失败
    • ¥100 支付宝网页转账系统不识别账号
    • ¥15 基于单片机的靶位控制系统
    • ¥15 真我手机蓝牙传输进度消息被关闭了,怎么打开?(关键词-消息通知)
    • ¥15 装 pytorch 的时候出了好多问题,遇到这种情况怎么处理?
    • ¥20 IOS游览器某宝手机网页版自动立即购买JavaScript脚本
    • ¥15 手机接入宽带网线,如何释放宽带全部速度