From 895a19f2dc60ddb72c6186b7702ade5a595576f2 Mon Sep 17 00:00:00 2001 From: Tao Wen Date: Tue, 20 Feb 2018 22:38:35 +0800 Subject: [PATCH] move json raw message --- reflect.go | 20 ++++---- reflect_json_raw_message.go | 57 ++++++++++++++++++++++ reflect_native.go | 94 ------------------------------------- reflect_struct_decoder.go | 60 +++++++++++++++++++++++ reflect_struct_encoder.go | 56 ++++++++++++---------- 5 files changed, 155 insertions(+), 132 deletions(-) create mode 100644 reflect_json_raw_message.go diff --git a/reflect.go b/reflect.go index 5dc6441..de4fdb2 100644 --- a/reflect.go +++ b/reflect.go @@ -106,13 +106,11 @@ func decoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecode func createDecoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { typeName := typ.String() - if typ == jsonRawMessageType { - return &jsonRawMessageCodec{} + decoder := createDecoderOfJsonRawMessage(cfg, prefix, typ) + if decoder != nil { + return decoder } - if typ == jsoniterRawMessageType { - return &jsoniterRawMessageCodec{} - } - decoder := createDecoderOfJsonNumber(cfg, prefix, typ) + decoder = createDecoderOfJsonNumber(cfg, prefix, typ) if decoder != nil { return decoder } @@ -295,13 +293,11 @@ func encoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncode } func createEncoderOfType(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { - if typ == jsonRawMessageType { - return &jsonRawMessageCodec{} + encoder := createEncoderOfJsonRawMessage(cfg, prefix, typ) + if encoder != nil { + return encoder } - if typ == jsoniterRawMessageType { - return &jsoniterRawMessageCodec{} - } - encoder := createEncoderOfJsonNumber(cfg, prefix, typ) + encoder = createEncoderOfJsonNumber(cfg, prefix, typ) if encoder != nil { return encoder } diff --git a/reflect_json_raw_message.go b/reflect_json_raw_message.go new file mode 100644 index 0000000..46f1675 --- /dev/null +++ b/reflect_json_raw_message.go @@ -0,0 +1,57 @@ +package jsoniter + +import ( + "unsafe" + "encoding/json" + "reflect" +) + +func createEncoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect.Type) ValEncoder { + if typ == jsonRawMessageType { + return &jsonRawMessageCodec{} + } + if typ == jsoniterRawMessageType { + return &jsoniterRawMessageCodec{} + } + return nil +} + +func createDecoderOfJsonRawMessage(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { + if typ == jsonRawMessageType { + return &jsonRawMessageCodec{} + } + if typ == jsoniterRawMessageType { + return &jsoniterRawMessageCodec{} + } + return nil +} + +type jsonRawMessageCodec struct { +} + +func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes()) +} + +func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteRaw(string(*((*json.RawMessage)(ptr)))) +} + +func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*json.RawMessage)(ptr))) == 0 +} + +type jsoniterRawMessageCodec struct { +} + +func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { + *((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes()) +} + +func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.WriteRaw(string(*((*RawMessage)(ptr)))) +} + +func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { + return len(*((*RawMessage)(ptr))) == 0 +} \ No newline at end of file diff --git a/reflect_native.go b/reflect_native.go index bc1c969..e2f8ad0 100644 --- a/reflect_native.go +++ b/reflect_native.go @@ -369,36 +369,6 @@ func (encoder *dynamicEncoder) IsEmpty(ptr unsafe.Pointer) bool { return encoder.valType.UnsafeIndirect(ptr) == nil } -type jsonRawMessageCodec struct { -} - -func (codec *jsonRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { - *((*json.RawMessage)(ptr)) = json.RawMessage(iter.SkipAndReturnBytes()) -} - -func (codec *jsonRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { - stream.WriteRaw(string(*((*json.RawMessage)(ptr)))) -} - -func (codec *jsonRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { - return len(*((*json.RawMessage)(ptr))) == 0 -} - -type jsoniterRawMessageCodec struct { -} - -func (codec *jsoniterRawMessageCodec) Decode(ptr unsafe.Pointer, iter *Iterator) { - *((*RawMessage)(ptr)) = RawMessage(iter.SkipAndReturnBytes()) -} - -func (codec *jsoniterRawMessageCodec) Encode(ptr unsafe.Pointer, stream *Stream) { - stream.WriteRaw(string(*((*RawMessage)(ptr)))) -} - -func (codec *jsoniterRawMessageCodec) IsEmpty(ptr unsafe.Pointer) bool { - return len(*((*RawMessage)(ptr))) == 0 -} - type base64Codec struct { sliceType *reflect2.UnsafeSliceType sliceDecoder ValDecoder @@ -448,67 +418,3 @@ func (codec *base64Codec) Encode(ptr unsafe.Pointer, stream *Stream) { func (codec *base64Codec) IsEmpty(ptr unsafe.Pointer) bool { return len(*((*[]byte)(ptr))) == 0 } - -type stringModeNumberDecoder struct { - elemDecoder ValDecoder -} - -func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { - c := iter.nextToken() - if c != '"' { - iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) - return - } - decoder.elemDecoder.Decode(ptr, iter) - if iter.Error != nil { - return - } - c = iter.readByte() - if c != '"' { - iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) - return - } -} - -type stringModeStringDecoder struct { - elemDecoder ValDecoder - cfg *frozenConfig -} - -func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { - decoder.elemDecoder.Decode(ptr, iter) - str := *((*string)(ptr)) - tempIter := decoder.cfg.BorrowIterator([]byte(str)) - defer decoder.cfg.ReturnIterator(tempIter) - *((*string)(ptr)) = tempIter.ReadString() -} - -type stringModeNumberEncoder struct { - elemEncoder ValEncoder -} - -func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { - stream.writeByte('"') - encoder.elemEncoder.Encode(ptr, stream) - stream.writeByte('"') -} - -func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool { - return encoder.elemEncoder.IsEmpty(ptr) -} - -type stringModeStringEncoder struct { - elemEncoder ValEncoder - cfg *frozenConfig -} - -func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { - tempStream := encoder.cfg.BorrowStream(nil) - defer encoder.cfg.ReturnStream(tempStream) - encoder.elemEncoder.Encode(ptr, tempStream) - stream.WriteString(string(tempStream.Buffer())) -} - -func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { - return encoder.elemEncoder.IsEmpty(ptr) -} diff --git a/reflect_struct_decoder.go b/reflect_struct_decoder.go index 4d03b35..5ba650d 100644 --- a/reflect_struct_decoder.go +++ b/reflect_struct_decoder.go @@ -8,6 +8,32 @@ import ( "unsafe" ) +func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { + bindings := map[string]*Binding{} + structDescriptor := describeStruct(cfg, prefix, typ) + for _, binding := range structDescriptor.Fields { + for _, fromName := range binding.FromNames { + old := bindings[fromName] + if old == nil { + bindings[fromName] = binding + continue + } + ignoreOld, ignoreNew := resolveConflictBinding(cfg, old, binding) + if ignoreOld { + delete(bindings, fromName) + } + if !ignoreNew { + bindings[fromName] = binding + } + } + } + fields := map[string]*structFieldDecoder{} + for k, binding := range bindings { + fields[k] = binding.Decoder.(*structFieldDecoder) + } + return createStructDecoder(cfg, typ, fields) +} + func createStructDecoder(cfg *frozenConfig, typ reflect.Type, fields map[string]*structFieldDecoder) ValDecoder { if cfg.disallowUnknownFields { return &generalStructDecoder{typ: typ, fields: fields, disallowUnknownFields: true} @@ -972,3 +998,37 @@ func (decoder *structFieldDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { iter.Error = fmt.Errorf("%s: %s", decoder.field.Name, iter.Error.Error()) } } + +type stringModeStringDecoder struct { + elemDecoder ValDecoder + cfg *frozenConfig +} + +func (decoder *stringModeStringDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + decoder.elemDecoder.Decode(ptr, iter) + str := *((*string)(ptr)) + tempIter := decoder.cfg.BorrowIterator([]byte(str)) + defer decoder.cfg.ReturnIterator(tempIter) + *((*string)(ptr)) = tempIter.ReadString() +} + +type stringModeNumberDecoder struct { + elemDecoder ValDecoder +} + +func (decoder *stringModeNumberDecoder) Decode(ptr unsafe.Pointer, iter *Iterator) { + c := iter.nextToken() + if c != '"' { + iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) + return + } + decoder.elemDecoder.Decode(ptr, iter) + if iter.Error != nil { + return + } + c = iter.readByte() + if c != '"' { + iter.ReportError("stringModeNumberDecoder", `expect ", but found `+string([]byte{c})) + return + } +} \ No newline at end of file diff --git a/reflect_struct_encoder.go b/reflect_struct_encoder.go index c9e79e7..5424c81 100644 --- a/reflect_struct_encoder.go +++ b/reflect_struct_encoder.go @@ -74,32 +74,6 @@ func resolveConflictBinding(cfg *frozenConfig, old, new *Binding) (ignoreOld, ig } } -func decoderOfStruct(cfg *frozenConfig, prefix string, typ reflect.Type) ValDecoder { - bindings := map[string]*Binding{} - structDescriptor := describeStruct(cfg, prefix, typ) - for _, binding := range structDescriptor.Fields { - for _, fromName := range binding.FromNames { - old := bindings[fromName] - if old == nil { - bindings[fromName] = binding - continue - } - ignoreOld, ignoreNew := resolveConflictBinding(cfg, old, binding) - if ignoreOld { - delete(bindings, fromName) - } - if !ignoreNew { - bindings[fromName] = binding - } - } - } - fields := map[string]*structFieldDecoder{} - for k, binding := range bindings { - fields[k] = binding.Decoder.(*structFieldDecoder) - } - return createStructDecoder(cfg, typ, fields) -} - type structFieldEncoder struct { field *reflect.StructField fieldEncoder ValEncoder @@ -179,3 +153,33 @@ func (encoder *emptyStructEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { func (encoder *emptyStructEncoder) IsEmpty(ptr unsafe.Pointer) bool { return false } + +type stringModeNumberEncoder struct { + elemEncoder ValEncoder +} + +func (encoder *stringModeNumberEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + stream.writeByte('"') + encoder.elemEncoder.Encode(ptr, stream) + stream.writeByte('"') +} + +func (encoder *stringModeNumberEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.elemEncoder.IsEmpty(ptr) +} + +type stringModeStringEncoder struct { + elemEncoder ValEncoder + cfg *frozenConfig +} + +func (encoder *stringModeStringEncoder) Encode(ptr unsafe.Pointer, stream *Stream) { + tempStream := encoder.cfg.BorrowStream(nil) + defer encoder.cfg.ReturnStream(tempStream) + encoder.elemEncoder.Encode(ptr, tempStream) + stream.WriteString(string(tempStream.Buffer())) +} + +func (encoder *stringModeStringEncoder) IsEmpty(ptr unsafe.Pointer) bool { + return encoder.elemEncoder.IsEmpty(ptr) +}