Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Load Flattened Data into Container (With arrays) #143

Open
WTIGER001 opened this issue Sep 4, 2024 · 2 comments
Open

Load Flattened Data into Container (With arrays) #143

WTIGER001 opened this issue Sep 4, 2024 · 2 comments

Comments

@WTIGER001
Copy link

I have tried the following with flattened JSON data like

`
flattenedData := map[string]interface{}{
"foo.arr.0": "apple",
"foo.arr.1": "banana",
"oarr.0.id": "id1",
"oarr.1.id": "id2",
}

// Create a new gabs container
container := gabs.New()

// Iterate through the flattened data and set values in the container
for path, value := range flattenedData {
	container.SetP(value, path)
}

// Print the nested JSON as a string
fmt.Println(container.StringIndent("", "  "))

`

I get

{ "foo": { "arr": { "0": "apple", "1": "banana" } }, "oarr": { "0": { "id": "id1" }, "1": { "id": "id2" } } }

Instead of

{ "foo": { "arr": [ "apple", "banana"] "oarr": [ { "id": "id1" }, { "id": "id2" } ] }

Is there a known way on how I can load this flattened data back into the container? It is using my array indexes as map keys right now.

@mihaitodor
Copy link
Contributor

mihaitodor commented Sep 5, 2024

Hey @WTIGER001 👋 Guess you can get away with something like this:

package main

import (
	"fmt"
	"slices"
	"strconv"

	"github.com/Jeffail/gabs/v2"
)

func main() {
	flattenedData := map[string]interface{}{
		"foo.arr.0": "apple",
		"foo.arr.1": "banana",
		"oarr.0.id": "id1",
		"oarr.1.id": "id2",
		"foo.bar":   "foobar",
	}

	// Create a new gabs container
	container := gabs.New()

	// Iterate through the flattened data and set values in the container
	for path, value := range flattenedData {
		segments := gabs.DotPathToSlice(path)

		isArray := false
		for loc, segment := range segments {
			if _, err := strconv.Atoi(segment); err == nil {
				isArray = true
				if _, err := container.ArrayCount(segments[:loc]...); err != nil {
					container.Array(segments[:loc]...)
				}
				if loc > 0 {
					if _, err := container.Set(value, slices.Replace(segments, loc, loc+1, "-")...); err != nil {
						panic(err)
					}
				} else {
					if err := container.ArrayAppend(value); err != nil {
						panic(err)
					}
				}
			}
		}
		if !isArray {
			if _, err := container.SetP(value, path); err != nil {
				panic(err)
			}
		}
	}

	// Print the nested JSON as a string
	fmt.Println(container.StringIndent("", "  "))
}

The trouble is that it doesn't validate the input so you could get some hard to debug issues. For example, if the flattened arrays are not in the right order, then the resulting arrays will not have the expected element order. Also, it doesn't detect gaps in arrays.

@WTIGER001
Copy link
Author

Thanks for that. That is an interesting approach.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants