浏览代码

#166 support ValidateJsonRawMessage in ConfigCompatibleWithStandardLibrary

Tao Wen 8 年之前
父节点
当前提交
90574c5ca3
共有 4 个文件被更改,包括 41 次插入4 次删除
  1. 25 2
      feature_config.go
  2. 1 1
      feature_reflect_native.go
  3. 1 1
      jsoniter_interface_test.go
  4. 14 0
      jsoniter_raw_message_test.go

+ 25 - 2
feature_config.go

@@ -18,6 +18,7 @@ type Config struct {
 	SortMapKeys             bool
 	UseNumber               bool
 	TagKey                  string
+	ValidateJsonRawMessage  bool
 }
 
 type frozenConfig struct {
@@ -53,8 +54,9 @@ var ConfigDefault = Config{
 
 // ConfigCompatibleWithStandardLibrary tries to be 100% compatible with standard library behavior
 var ConfigCompatibleWithStandardLibrary = Config{
-	EscapeHTML:  true,
-	SortMapKeys: true,
+	EscapeHTML:             true,
+	SortMapKeys:            true,
+	ValidateJsonRawMessage: true,
 }.Froze()
 
 // ConfigFastest marshals float with only 6 digits precision
@@ -83,10 +85,31 @@ func (cfg Config) Froze() API {
 	if cfg.UseNumber {
 		frozenConfig.useNumber()
 	}
+	if cfg.ValidateJsonRawMessage {
+		frozenConfig.validateJsonRawMessage()
+	}
 	frozenConfig.configBeforeFrozen = cfg
 	return frozenConfig
 }
 
+func (cfg *frozenConfig) validateJsonRawMessage() {
+	encoder := &funcEncoder{func(ptr unsafe.Pointer, stream *Stream) {
+		rawMessage := *(*json.RawMessage)(ptr)
+		iter := cfg.BorrowIterator([]byte(rawMessage))
+		iter.Read()
+		if iter.Error != nil {
+			stream.WriteRaw("null")
+		} else {
+			cfg.ReturnIterator(iter)
+			stream.WriteRaw(string(rawMessage))
+		}
+	}, func(ptr unsafe.Pointer) bool {
+		return false
+	}}
+	cfg.addEncoderToCache(reflect.TypeOf((*json.RawMessage)(nil)).Elem(), encoder)
+	cfg.addEncoderToCache(reflect.TypeOf((*RawMessage)(nil)).Elem(), encoder)
+}
+
 func (cfg *frozenConfig) useNumber() {
 	cfg.addDecoderToCache(reflect.TypeOf((*interface{})(nil)).Elem(), &funcDecoder{func(ptr unsafe.Pointer, iter *Iterator) {
 		if iter.WhatIsNext() == NumberValue {

+ 1 - 1
feature_reflect_native.go

@@ -4,8 +4,8 @@ import (
 	"encoding"
 	"encoding/base64"
 	"encoding/json"
-	"unsafe"
 	"reflect"
+	"unsafe"
 )
 
 type stringCodec struct {

+ 1 - 1
jsoniter_interface_test.go

@@ -2,10 +2,10 @@ package jsoniter
 
 import (
 	"encoding/json"
+	"fmt"
 	"github.com/stretchr/testify/require"
 	"testing"
 	"unsafe"
-	"fmt"
 )
 
 func Test_write_array_of_interface(t *testing.T) {

+ 14 - 0
jsoniter_raw_message_test.go

@@ -72,3 +72,17 @@ func Test_encode_map_of_jsoniter_raw_message(t *testing.T) {
 	should.Nil(err)
 	should.Equal(`{"hello":[]}`, output)
 }
+
+func Test_marshal_invalid_json_raw_message(t *testing.T) {
+	type A struct {
+		Raw json.RawMessage `json:"raw"`
+	}
+	message := []byte(`{}`)
+
+	a := A{}
+	should := require.New(t)
+	should.Nil(ConfigCompatibleWithStandardLibrary.Unmarshal(message, &a))
+	aout, aouterr := ConfigCompatibleWithStandardLibrary.Marshal(&a)
+	should.Equal(`{"raw":null}`, string(aout))
+	should.Nil(aouterr)
+}