feat: raw map parser.
This commit is contained in:
parent
0186c31d59
commit
c42f1b7a50
13 changed files with 901 additions and 18 deletions
|
@ -57,6 +57,11 @@ func (m metadata) add(rootType reflect.Type, node *Node) error {
|
|||
rType = rootType.Elem()
|
||||
}
|
||||
|
||||
if rType.Kind() == reflect.Map && rType.Elem().Kind() == reflect.Interface {
|
||||
addRawValue(node)
|
||||
return nil
|
||||
}
|
||||
|
||||
field, err := m.findTypedField(rType, node)
|
||||
if err != nil {
|
||||
return err
|
||||
|
@ -88,6 +93,11 @@ func (m metadata) add(rootType reflect.Type, node *Node) error {
|
|||
}
|
||||
|
||||
if fType.Kind() == reflect.Map {
|
||||
if fType.Elem().Kind() == reflect.Interface {
|
||||
addRawValue(node)
|
||||
return nil
|
||||
}
|
||||
|
||||
for _, child := range node.Children {
|
||||
// elem is a map entry value type
|
||||
elem := fType.Elem()
|
||||
|
@ -194,3 +204,75 @@ func isSupportedType(field reflect.StructField) error {
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
/*
|
||||
RawMap section
|
||||
*/
|
||||
|
||||
func addRawValue(node *Node) {
|
||||
if node.RawValue == nil {
|
||||
node.RawValue = nodeToRawMap(node)
|
||||
}
|
||||
|
||||
node.Children = nil
|
||||
}
|
||||
|
||||
func nodeToRawMap(node *Node) map[string]interface{} {
|
||||
result := map[string]interface{}{}
|
||||
|
||||
squashNode(node, result, true)
|
||||
|
||||
return result
|
||||
}
|
||||
|
||||
func squashNode(node *Node, acc map[string]interface{}, root bool) {
|
||||
if len(node.Children) == 0 {
|
||||
acc[node.Name] = node.Value
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// slice
|
||||
if isArrayKey(node.Children[0].Name) {
|
||||
var accChild []interface{}
|
||||
|
||||
for _, child := range node.Children {
|
||||
tmp := map[string]interface{}{}
|
||||
squashNode(child, tmp, false)
|
||||
accChild = append(accChild, tmp[child.Name])
|
||||
}
|
||||
|
||||
acc[node.Name] = accChild
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// map
|
||||
var accChild map[string]interface{}
|
||||
if root {
|
||||
accChild = acc
|
||||
} else {
|
||||
accChild = typedRawMap(acc, node.Name)
|
||||
}
|
||||
|
||||
for _, child := range node.Children {
|
||||
squashNode(child, accChild, false)
|
||||
}
|
||||
}
|
||||
|
||||
func typedRawMap(m map[string]interface{}, k string) map[string]interface{} {
|
||||
if m[k] == nil {
|
||||
m[k] = map[string]interface{}{}
|
||||
}
|
||||
|
||||
r, ok := m[k].(map[string]interface{})
|
||||
if !ok {
|
||||
panic(fmt.Sprintf("unsupported value (key: %s): %T", k, m[k]))
|
||||
}
|
||||
|
||||
return r
|
||||
}
|
||||
|
||||
func isArrayKey(name string) bool {
|
||||
return name[0] == '[' && name[len(name)-1] == ']'
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue