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

add new json item not sync in memory #114

Open
perrynzhou opened this issue Oct 22, 2021 · 2 comments
Open

add new json item not sync in memory #114

perrynzhou opened this issue Oct 22, 2021 · 2 comments

Comments

@perrynzhou
Copy link

perrynzhou commented Oct 22, 2021

  • plateform
mac os
  • code
func main() {
	b,_ := ioutil.ReadFile("./test_cluster.conf")
	jsoner,_ := gabs.ParseJSON(b)
	key :="cluster/test/demo"
	tmpMap := map[string]string{"aaa":"bbb"}
	keys_args  := strings.Split(key,"/")
	jsoner.Set(tmpMap,keys_args...)
	// if add that: jsoner,_ = gabs.ParseJSON(jsoner.Bytes()),i can search data
	ioutil.WriteFile("./temp.json",jsoner.BytesIndent(" "," "),os.ModePerm)
	c :=jsoner.Search(keys_args...)
	if c== nil {
		log.Println("c is nil")
	}else {
                //c.ChildrenMap is empty
		log.Println("c is not nil:",c.ChildrenMap())
		for k,v :=range c.ChildrenMap() {
			log.Printf("%v=%v",k,v)
		}
	}
}
@mihaitodor
Copy link
Contributor

@perrynzhou Thank you for opening this issue and sorry for the late reply! Unfortunately, there isn't enough information in your report to investigate the problem. Would you mind providing the contents of test_cluster.conf and the expected outcome? I'm guessing you're running into something similar to #108, but not sure.

@flowchartsman
Copy link
Contributor

I believe what he's reporting here is something I ran into during testing attempting to set a map[string]string value:

Code

package main

import (
	"fmt"

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

func main() {
	c1, _ := gabs.ParseJSON([]byte(`{"a":"a"}`))
	c2, _ := gabs.ParseJSON([]byte(`{"a":"a"}`))
	c1.Set("test", "b", "c")                     // can retrieve fine
	c2.Set(map[string]string{"c": "test2"}, "b") // won't be able to retrieve

	fmt.Println("c1->b.c", c1.S("b", "c"))
	fmt.Println("c2->b.c", c2.S("b", "c"))

	c1j, _ := c1.MarshalJSON()
	fmt.Printf("c1 .MarshalJSON():\n%s\n", string(c1j))

	c2j, _ := c2.MarshalJSON()
	fmt.Printf("c2 .MarshalJSON():\n%s\n", string(c2j))
}

Output

c1->b.c null
c2->b.c null
c1->d.e "test2"
c2->d.e null
c1 .MarshalJSON():
{"a":"a","d":{"e":"test2"}}
c2 .MarshalJSON():
{"a":"a","d":{"e":"test2"}}

The reason for this is that on gabs.go:322 the hierarchy will bottom out and whatever value you are adding will be put into the map[string]...interface{} hierarchy as-is. So, in this case, it inserts the map just fine, but, when S("b","c") is called, the hierarchy loop will reach b, and, instead of the expected map[string]interface{} or []interface{}, which it knows how to traverse, it will find something else and return immediately.

This is confusing, since the result will still marshal correctly, since json.Marshal will transparently navigate the nested hierarchy, marshalling what it finds.

Workaround

The quick fix is just to use map[string]any/ map[string]interface{} which will work fine, so long as any deeper hierarchy is also map[string]any:

c2, _ = gabs.ParseJSON([]byte(`{"a":"a"}`))
c2.Set(map[string]any{"c": "test2"}, "b") // works again!
fmt.Println("c2->b.c", c2.S("b", "c"))

// ouput: c2->b.c "test2"

Fix

The long-term "fix" is either:

  • Document that adding anything with deeper nesting is unpredictable and may cause problems on retrieval, or
  • Reflect on the incoming value on set and, if the value is not a scalar, make a container at that location by either json.Marshal ->gabs.ParseJson -> Data() or ripping a page from the mapstructure book, and just crawling the value. You could also add a new method that explicitly does this.

This means that you'll lose any ability you had before to call S/Search/Path and get back something you can type assert and call methods on, but since this is a package for "dealing with dynamic or unknown JSON structures in Go", and there isn't any documentation that I can find that explicitly mentions that, you could write that off as an "unsupported use-case" anyway. 🤷

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

3 participants