From 9072d798c89c152c22f56eca6ae02d1bbbfd37e7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bj=C3=B6rn=20Benouarets?= Date: Thu, 22 Jan 2026 12:14:49 +0100 Subject: [PATCH] init: Initial commit --- README.md | 60 ++++++++++++++++++++++++++++++++ go.mod | 3 ++ mapper.go | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 163 insertions(+) create mode 100644 README.md create mode 100644 go.mod create mode 100644 mapper.go diff --git a/README.md b/README.md new file mode 100644 index 0000000..246ab3e --- /dev/null +++ b/README.md @@ -0,0 +1,60 @@ +# Go JSON Mapper (gojsonmapper) + +This is a simple library that allows you to map different JSON objects to each other. + +## Example + +This example shows how to map a JSON object to another JSON object. + +### Mapping + +```json +{ + "name": "data.name", + "address": "data.addresses[0]" +} +```` + +### Input JSON + +```json +{ + "data": { + "name": "John Doe", + "addresses": [ + "123 Main St" + ] + } +} +``` + +### Output JSON + +```json +{ + "name": "John Doe", + "address": "123 Main St" +} +``` + +## Usage + +### Read Mapping + +```go +mapping, err := ReadMapping("mapping.json") +if err != nil { + log.Fatal(err) +} +``` + +### Map Input + +```go +mapper := NewMapper(mapping) +output, err := mapper.Map(input) +if err != nil { + log.Fatal(err) +} +fmt.Println(output) +``` \ No newline at end of file diff --git a/go.mod b/go.mod new file mode 100644 index 0000000..a78aedf --- /dev/null +++ b/go.mod @@ -0,0 +1,3 @@ +module git.secnex.io/secnex/gojsonmapper + +go 1.25.5 diff --git a/mapper.go b/mapper.go new file mode 100644 index 0000000..8975118 --- /dev/null +++ b/mapper.go @@ -0,0 +1,100 @@ +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 +}