101 lines
2.1 KiB
Go
101 lines
2.1 KiB
Go
package gojsonmapper
|
|
|
|
import (
|
|
"encoding/json"
|
|
"fmt"
|
|
"os"
|
|
"strings"
|
|
)
|
|
|
|
type Mapper struct {
|
|
mapping map[string]string
|
|
}
|
|
|
|
func ReadMapping(path string) (map[string]string, error) {
|
|
jsonData, err := os.ReadFile(path)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var mapping map[string]string
|
|
err = json.Unmarshal(jsonData, &mapping)
|
|
return mapping, nil
|
|
}
|
|
|
|
func NewMapper(mapping map[string]string) *Mapper {
|
|
return &Mapper{mapping: mapping}
|
|
}
|
|
|
|
func (m *Mapper) Map(input map[string]interface{}) (map[string]interface{}, error) {
|
|
output := make(map[string]interface{})
|
|
for key, path := range m.mapping {
|
|
output[key] = navigatePath(input, path)
|
|
}
|
|
return output, nil
|
|
}
|
|
|
|
func navigatePath(current map[string]interface{}, path string) interface{} {
|
|
parts := strings.Split(path, ".")
|
|
for i, part := range parts {
|
|
isLast := i == len(parts)-1
|
|
if strings.Contains(part, "[") && strings.HasSuffix(part, "]") {
|
|
key := part[:strings.Index(part, "[")]
|
|
indexStr := part[strings.Index(part, "[")+1 : len(part)-1]
|
|
|
|
if current[key] == nil {
|
|
return nil
|
|
}
|
|
arr, ok := current[key].([]interface{})
|
|
if !ok {
|
|
return nil
|
|
}
|
|
|
|
// Handle mapping all elements: key[]
|
|
if indexStr == "" {
|
|
if isLast {
|
|
return arr
|
|
}
|
|
remainingPath := strings.Join(parts[i+1:], ".")
|
|
result := make([]interface{}, len(arr))
|
|
for j, item := range arr {
|
|
if nestedMap, ok := item.(map[string]interface{}); ok {
|
|
result[j] = navigatePath(nestedMap, remainingPath)
|
|
}
|
|
}
|
|
return result
|
|
}
|
|
|
|
// Handle specific index: key[0]
|
|
var index int
|
|
fmt.Sscanf(indexStr, "%d", &index)
|
|
if index < 0 || index >= len(arr) {
|
|
return nil
|
|
}
|
|
|
|
if isLast {
|
|
return arr[index]
|
|
}
|
|
|
|
if nestedMap, ok := arr[index].(map[string]interface{}); ok {
|
|
remainingPath := strings.Join(parts[i+1:], ".")
|
|
return navigatePath(nestedMap, remainingPath)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
// Regular key access
|
|
if isLast {
|
|
return current[part]
|
|
}
|
|
|
|
if current[part] == nil {
|
|
return nil
|
|
}
|
|
var ok bool
|
|
current, ok = current[part].(map[string]interface{})
|
|
if !ok {
|
|
return nil
|
|
}
|
|
}
|
|
return current
|
|
}
|