mirror of
https://github.com/json-iterator/go.git
synced 2025-03-26 21:12:40 +02:00
#23 hide unexported fields by default
This commit is contained in:
parent
5fbe4e387d
commit
6126a6d3ca
@ -6,32 +6,23 @@ import (
|
||||
"reflect"
|
||||
"unsafe"
|
||||
"strings"
|
||||
"unicode"
|
||||
)
|
||||
|
||||
func encoderOfStruct(typ reflect.Type) (Encoder, error) {
|
||||
structEncoder_ := &structEncoder{}
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
var fieldNames []string
|
||||
var extensionProvidedFieldNames []string
|
||||
for _, extension := range extensions {
|
||||
alternativeFieldNames, _ := extension(typ, &field)
|
||||
if alternativeFieldNames != nil {
|
||||
fieldNames = alternativeFieldNames
|
||||
extensionProvidedFieldNames = alternativeFieldNames
|
||||
}
|
||||
}
|
||||
tagParts := strings.Split(field.Tag.Get("json"), ",")
|
||||
// if fieldNames set by extension, use theirs, otherwise try tags
|
||||
if fieldNames == nil {
|
||||
/// tagParts[0] always present, even if no tags
|
||||
switch tagParts[0] {
|
||||
case "":
|
||||
fieldNames = []string{field.Name}
|
||||
case "-":
|
||||
fieldNames = []string{}
|
||||
default:
|
||||
fieldNames = []string{tagParts[0]}
|
||||
}
|
||||
}
|
||||
fieldNames := calcFieldNames(field.Name, tagParts[0], extensionProvidedFieldNames)
|
||||
omitempty := false
|
||||
for _, tagPart := range tagParts {
|
||||
if tagPart == "omitempty" {
|
||||
@ -66,11 +57,11 @@ func decoderOfStruct(typ reflect.Type) (Decoder, error) {
|
||||
for i := 0; i < typ.NumField(); i++ {
|
||||
field := typ.Field(i)
|
||||
fieldDecoderKey := fmt.Sprintf("%s/%s", typ.String(), field.Name)
|
||||
var fieldNames []string
|
||||
var extensionProviedFieldNames []string
|
||||
for _, extension := range extensions {
|
||||
alternativeFieldNames, fun := extension(typ, &field)
|
||||
if alternativeFieldNames != nil {
|
||||
fieldNames = alternativeFieldNames
|
||||
extensionProviedFieldNames = alternativeFieldNames
|
||||
}
|
||||
if fun != nil {
|
||||
fieldDecoders[fieldDecoderKey] = &funcDecoder{fun}
|
||||
@ -78,18 +69,7 @@ func decoderOfStruct(typ reflect.Type) (Decoder, error) {
|
||||
}
|
||||
decoder := fieldDecoders[fieldDecoderKey]
|
||||
tagParts := strings.Split(field.Tag.Get("json"), ",")
|
||||
// if fieldNames set by extension, use theirs, otherwise try tags
|
||||
if fieldNames == nil {
|
||||
/// tagParts[0] always present, even if no tags
|
||||
switch tagParts[0] {
|
||||
case "":
|
||||
fieldNames = []string{field.Name}
|
||||
case "-":
|
||||
fieldNames = []string{}
|
||||
default:
|
||||
fieldNames = []string{tagParts[0]}
|
||||
}
|
||||
}
|
||||
fieldNames := calcFieldNames(field.Name, tagParts[0], extensionProviedFieldNames)
|
||||
if decoder == nil && len(fieldNames) > 0 {
|
||||
var err error
|
||||
decoder, err = decoderOfType(field.Type)
|
||||
@ -107,6 +87,36 @@ func decoderOfStruct(typ reflect.Type) (Decoder, error) {
|
||||
return createStructDecoder(typ, fields)
|
||||
}
|
||||
|
||||
func calcFieldNames(originalFieldName string, tagProvidedFieldName string, extensionProvidedFieldNames []string) []string {
|
||||
// tag => extension => exported? => original
|
||||
isNotExported := unicode.IsLower(rune(originalFieldName[0]))
|
||||
var fieldNames []string
|
||||
/// tagParts[0] always present, even if no tags
|
||||
switch tagProvidedFieldName {
|
||||
case "":
|
||||
if extensionProvidedFieldNames != nil {
|
||||
fieldNames = extensionProvidedFieldNames
|
||||
} else {
|
||||
if isNotExported {
|
||||
fieldNames = []string{}
|
||||
} else {
|
||||
fieldNames = []string{originalFieldName}
|
||||
}
|
||||
}
|
||||
case "-":
|
||||
fieldNames = []string{}
|
||||
default:
|
||||
fieldNames = []string{tagProvidedFieldName}
|
||||
}
|
||||
return fieldNames
|
||||
}
|
||||
|
||||
func EnableUnexportedStructFieldsSupport() {
|
||||
RegisterExtension(func(type_ reflect.Type, field *reflect.StructField) ([]string, DecoderFunc) {
|
||||
return []string{field.Name}, nil
|
||||
})
|
||||
}
|
||||
|
||||
func createStructDecoder(typ reflect.Type, fields map[string]*structFieldDecoder) (Decoder, error) {
|
||||
knownHash := map[int32]struct{}{
|
||||
0: struct{}{},
|
||||
|
@ -103,3 +103,22 @@ func Test_customize_field_by_extension(t *testing.T) {
|
||||
t.Fatal(obj.field1)
|
||||
}
|
||||
}
|
||||
|
||||
func Test_unexported_fields(t *testing.T) {
|
||||
EnableUnexportedStructFieldsSupport()
|
||||
should := require.New(t)
|
||||
type TestObject struct {
|
||||
field1 string
|
||||
field2 string `json:"field-2"`
|
||||
}
|
||||
obj := TestObject{}
|
||||
obj.field1 = "hello"
|
||||
should.Nil(UnmarshalFromString(`{}`, &obj))
|
||||
should.Equal("hello", obj.field1)
|
||||
should.Nil(UnmarshalFromString(`{"field1": "world", "field-2": "abc"}`, &obj))
|
||||
should.Equal("world", obj.field1)
|
||||
should.Equal("abc", obj.field2)
|
||||
str, err := MarshalToString(obj)
|
||||
should.Nil(err)
|
||||
should.Equal(`{"field1":"world","field-2":"abc"}`, str)
|
||||
}
|
@ -9,106 +9,106 @@ import (
|
||||
func Test_decode_one_field_struct(t *testing.T) {
|
||||
should := require.New(t)
|
||||
type TestObject struct {
|
||||
field1 string
|
||||
Field1 string
|
||||
}
|
||||
obj := TestObject{}
|
||||
should.Nil(UnmarshalFromString(`{}`, &obj))
|
||||
should.Equal("", obj.field1)
|
||||
should.Nil(UnmarshalFromString(`{"field1": "hello"}`, &obj))
|
||||
should.Equal("hello", obj.field1)
|
||||
should.Equal("", obj.Field1)
|
||||
should.Nil(UnmarshalFromString(`{"Field1": "hello"}`, &obj))
|
||||
should.Equal("hello", obj.Field1)
|
||||
}
|
||||
|
||||
func Test_decode_two_fields_struct(t *testing.T) {
|
||||
should := require.New(t)
|
||||
type TestObject struct {
|
||||
field1 string
|
||||
field2 string
|
||||
Field1 string
|
||||
Field2 string
|
||||
}
|
||||
obj := TestObject{}
|
||||
should.Nil(UnmarshalFromString(`{}`, &obj))
|
||||
should.Equal("", obj.field1)
|
||||
should.Nil(UnmarshalFromString(`{"field1": "a", "field2": "b"}`, &obj))
|
||||
should.Equal("a", obj.field1)
|
||||
should.Equal("b", obj.field2)
|
||||
should.Equal("", obj.Field1)
|
||||
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b"}`, &obj))
|
||||
should.Equal("a", obj.Field1)
|
||||
should.Equal("b", obj.Field2)
|
||||
}
|
||||
|
||||
func Test_decode_three_fields_struct(t *testing.T) {
|
||||
should := require.New(t)
|
||||
type TestObject struct {
|
||||
field1 string
|
||||
field2 string
|
||||
field3 string
|
||||
Field1 string
|
||||
Field2 string
|
||||
Field3 string
|
||||
}
|
||||
obj := TestObject{}
|
||||
should.Nil(UnmarshalFromString(`{}`, &obj))
|
||||
should.Equal("", obj.field1)
|
||||
should.Nil(UnmarshalFromString(`{"field1": "a", "field2": "b", "field3": "c"}`, &obj))
|
||||
should.Equal("a", obj.field1)
|
||||
should.Equal("b", obj.field2)
|
||||
should.Equal("c", obj.field3)
|
||||
should.Equal("", obj.Field1)
|
||||
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b", "Field3": "c"}`, &obj))
|
||||
should.Equal("a", obj.Field1)
|
||||
should.Equal("b", obj.Field2)
|
||||
should.Equal("c", obj.Field3)
|
||||
}
|
||||
|
||||
func Test_decode_four_fields_struct(t *testing.T) {
|
||||
should := require.New(t)
|
||||
type TestObject struct {
|
||||
field1 string
|
||||
field2 string
|
||||
field3 string
|
||||
field4 string
|
||||
Field1 string
|
||||
Field2 string
|
||||
Field3 string
|
||||
Field4 string
|
||||
}
|
||||
obj := TestObject{}
|
||||
should.Nil(UnmarshalFromString(`{}`, &obj))
|
||||
should.Equal("", obj.field1)
|
||||
should.Nil(UnmarshalFromString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d"}`, &obj))
|
||||
should.Equal("a", obj.field1)
|
||||
should.Equal("b", obj.field2)
|
||||
should.Equal("c", obj.field3)
|
||||
should.Equal("d", obj.field4)
|
||||
should.Equal("", obj.Field1)
|
||||
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d"}`, &obj))
|
||||
should.Equal("a", obj.Field1)
|
||||
should.Equal("b", obj.Field2)
|
||||
should.Equal("c", obj.Field3)
|
||||
should.Equal("d", obj.Field4)
|
||||
}
|
||||
|
||||
func Test_decode_five_fields_struct(t *testing.T) {
|
||||
should := require.New(t)
|
||||
type TestObject struct {
|
||||
field1 string
|
||||
field2 string
|
||||
field3 string
|
||||
field4 string
|
||||
field5 string
|
||||
Field1 string
|
||||
Field2 string
|
||||
Field3 string
|
||||
Field4 string
|
||||
Field5 string
|
||||
}
|
||||
obj := TestObject{}
|
||||
should.Nil(UnmarshalFromString(`{}`, &obj))
|
||||
should.Equal("", obj.field1)
|
||||
should.Nil(UnmarshalFromString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d", "field5": "e"}`, &obj))
|
||||
should.Equal("a", obj.field1)
|
||||
should.Equal("b", obj.field2)
|
||||
should.Equal("c", obj.field3)
|
||||
should.Equal("d", obj.field4)
|
||||
should.Equal("e", obj.field5)
|
||||
should.Equal("", obj.Field1)
|
||||
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj))
|
||||
should.Equal("a", obj.Field1)
|
||||
should.Equal("b", obj.Field2)
|
||||
should.Equal("c", obj.Field3)
|
||||
should.Equal("d", obj.Field4)
|
||||
should.Equal("e", obj.Field5)
|
||||
}
|
||||
|
||||
func Test_decode_ten_fields_struct(t *testing.T) {
|
||||
should := require.New(t)
|
||||
type TestObject struct {
|
||||
field1 string
|
||||
field2 string
|
||||
field3 string
|
||||
field4 string
|
||||
field5 string
|
||||
field6 string
|
||||
field7 string
|
||||
field8 string
|
||||
field9 string
|
||||
field10 string
|
||||
Field1 string
|
||||
Field2 string
|
||||
Field3 string
|
||||
Field4 string
|
||||
Field5 string
|
||||
Field6 string
|
||||
Field7 string
|
||||
Field8 string
|
||||
Field9 string
|
||||
Field10 string
|
||||
}
|
||||
obj := TestObject{}
|
||||
should.Nil(UnmarshalFromString(`{}`, &obj))
|
||||
should.Equal("", obj.field1)
|
||||
should.Nil(UnmarshalFromString(`{"field1": "a", "field2": "b", "field3": "c", "field4": "d", "field5": "e"}`, &obj))
|
||||
should.Equal("a", obj.field1)
|
||||
should.Equal("b", obj.field2)
|
||||
should.Equal("c", obj.field3)
|
||||
should.Equal("d", obj.field4)
|
||||
should.Equal("e", obj.field5)
|
||||
should.Equal("", obj.Field1)
|
||||
should.Nil(UnmarshalFromString(`{"Field1": "a", "Field2": "b", "Field3": "c", "Field4": "d", "Field5": "e"}`, &obj))
|
||||
should.Equal("a", obj.Field1)
|
||||
should.Equal("b", obj.Field2)
|
||||
should.Equal("c", obj.Field3)
|
||||
should.Equal("d", obj.Field4)
|
||||
should.Equal("e", obj.Field5)
|
||||
}
|
||||
|
||||
func Test_decode_struct_field_with_tag(t *testing.T) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user