mirror of https://github.com/goccy/go-json.git
add filter rule
This commit is contained in:
parent
bcaf36681a
commit
d11fc7fe6c
|
@ -168,6 +168,27 @@ func (c *StructCode) ToOpcode() []*Opcode {
|
||||||
return []*Opcode{}
|
return []*Opcode{}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *StructCode) removeFieldsByTags(tags runtime.StructTags) {
|
||||||
|
fields := make([]*StructFieldCode, 0, len(c.fields))
|
||||||
|
for _, field := range c.fields {
|
||||||
|
if field.isAnonymous {
|
||||||
|
structCode := field.getAnonymousStruct()
|
||||||
|
if structCode != nil {
|
||||||
|
structCode.removeFieldsByTags(tags)
|
||||||
|
if len(structCode.fields) > 0 {
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if tags.ExistsKey(field.key) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
fields = append(fields, field)
|
||||||
|
}
|
||||||
|
c.fields = fields
|
||||||
|
}
|
||||||
|
|
||||||
type StructFieldCode struct {
|
type StructFieldCode struct {
|
||||||
typ *runtime.Type
|
typ *runtime.Type
|
||||||
key string
|
key string
|
||||||
|
@ -181,7 +202,14 @@ type StructFieldCode struct {
|
||||||
isNextOpPtrType bool
|
isNextOpPtrType bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *StructFieldCode) toInlineCode() []*StructFieldCode {
|
func (c *StructFieldCode) getAnonymousStruct() *StructCode {
|
||||||
|
if !c.isAnonymous {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
code, ok := c.value.(*StructCode)
|
||||||
|
if ok {
|
||||||
|
return code
|
||||||
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -486,50 +514,87 @@ func compileStruct2(ctx *compileContext, isPtr bool) (*StructCode, error) {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if field.isAnonymous {
|
if field.isAnonymous {
|
||||||
structCode, ok := field.value.(*StructCode)
|
structCode := field.getAnonymousStruct()
|
||||||
if ok {
|
if structCode != nil {
|
||||||
for _, field := range structCode.fields {
|
structCode.removeFieldsByTags(tags)
|
||||||
if tags.ExistsKey(field.key) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
fields = append(fields, field)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
fields = append(fields, field)
|
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
fields = append(fields, field)
|
|
||||||
}
|
}
|
||||||
|
fields = append(fields, field)
|
||||||
}
|
}
|
||||||
|
fieldMap := getFieldMap(fields)
|
||||||
|
duplicatedFieldMap := getDuplicatedFieldMap(fieldMap)
|
||||||
|
code.fields = filteredDuplicatedFields(fields, duplicatedFieldMap)
|
||||||
|
return code, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFieldMap(fields []*StructFieldCode) map[string][]*StructFieldCode {
|
||||||
fieldMap := map[string][]*StructFieldCode{}
|
fieldMap := map[string][]*StructFieldCode{}
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
|
if field.isAnonymous {
|
||||||
|
structCode := field.getAnonymousStruct()
|
||||||
|
if structCode != nil {
|
||||||
|
for k, v := range getFieldMap(structCode.fields) {
|
||||||
|
fieldMap[k] = append(fieldMap[k], v...)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
fieldMap[field.key] = append(fieldMap[field.key], field)
|
fieldMap[field.key] = append(fieldMap[field.key], field)
|
||||||
}
|
}
|
||||||
removeFieldKey := map[string]struct{}{}
|
return fieldMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func getDuplicatedFieldMap(fieldMap map[string][]*StructFieldCode) map[*StructFieldCode]struct{} {
|
||||||
|
duplicatedFieldMap := map[*StructFieldCode]struct{}{}
|
||||||
for _, fields := range fieldMap {
|
for _, fields := range fieldMap {
|
||||||
if len(fields) == 1 {
|
if len(fields) == 1 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
var foundTaggedKey bool
|
if isTaggedKeyOnly(fields) {
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
if field.isTaggedKey {
|
if field.isTaggedKey {
|
||||||
if foundTaggedKey {
|
continue
|
||||||
removeFieldKey[field.key] = struct{}{}
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
foundTaggedKey = true
|
duplicatedFieldMap[field] = struct{}{}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, field := range fields {
|
||||||
|
duplicatedFieldMap[field] = struct{}{}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return duplicatedFieldMap
|
||||||
|
}
|
||||||
|
|
||||||
|
func filteredDuplicatedFields(fields []*StructFieldCode, duplicatedFieldMap map[*StructFieldCode]struct{}) []*StructFieldCode {
|
||||||
filteredFields := make([]*StructFieldCode, 0, len(fields))
|
filteredFields := make([]*StructFieldCode, 0, len(fields))
|
||||||
for _, field := range fields {
|
for _, field := range fields {
|
||||||
if _, exists := removeFieldKey[field.key]; exists {
|
if field.isAnonymous {
|
||||||
|
structCode := field.getAnonymousStruct()
|
||||||
|
if structCode != nil {
|
||||||
|
structCode.fields = filteredDuplicatedFields(structCode.fields, duplicatedFieldMap)
|
||||||
|
if len(structCode.fields) > 0 {
|
||||||
|
filteredFields = append(filteredFields, field)
|
||||||
|
}
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if _, exists := duplicatedFieldMap[field]; exists {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
filteredFields = append(filteredFields, field)
|
filteredFields = append(filteredFields, field)
|
||||||
}
|
}
|
||||||
code.fields = filteredFields
|
return filteredFields
|
||||||
return code, nil
|
}
|
||||||
|
|
||||||
|
func isTaggedKeyOnly(fields []*StructFieldCode) bool {
|
||||||
|
var taggedKeyFieldCount int
|
||||||
|
for _, field := range fields {
|
||||||
|
if field.isTaggedKey {
|
||||||
|
taggedKeyFieldCount++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return taggedKeyFieldCount == 1
|
||||||
}
|
}
|
||||||
|
|
||||||
func typeToStructTags(typ *runtime.Type) runtime.StructTags {
|
func typeToStructTags(typ *runtime.Type) runtime.StructTags {
|
||||||
|
|
|
@ -1316,7 +1316,6 @@ func compileStruct(ctx *compileContext, isPtr bool) (*Opcode, error) {
|
||||||
fieldPtrIndex := ctx.ptrIndex
|
fieldPtrIndex := ctx.ptrIndex
|
||||||
ctx.incIndex()
|
ctx.incIndex()
|
||||||
|
|
||||||
fmt.Println("fieldOpcodeIndex = ", fieldOpcodeIndex)
|
|
||||||
nilcheck := true
|
nilcheck := true
|
||||||
addrForMarshaler := false
|
addrForMarshaler := false
|
||||||
isIndirectSpecialCase := isPtr && i == 0 && fieldNum == 1
|
isIndirectSpecialCase := isPtr && i == 0 && fieldNum == 1
|
||||||
|
|
Loading…
Reference in New Issue