gabs icon indicating copy to clipboard operation
gabs copied to clipboard

Load Flattened Data into Container (With arrays)

Open WTIGER001 opened this issue 1 year ago • 2 comments

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.

WTIGER001 avatar Sep 04 '24 17:09 WTIGER001

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.

mihaitodor avatar Sep 05 '24 17:09 mihaitodor

Thanks for that. That is an interesting approach.

WTIGER001 avatar Sep 06 '24 01:09 WTIGER001