init: Initial commit

This commit is contained in:
Björn Benouarets
2026-01-22 12:14:49 +01:00
commit 9072d798c8
3 changed files with 163 additions and 0 deletions

60
README.md Normal file
View File

@@ -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)
```

3
go.mod Normal file
View File

@@ -0,0 +1,3 @@
module git.secnex.io/secnex/gojsonmapper
go 1.25.5

100
mapper.go Normal file
View File

@@ -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
}