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

linkedhashmap maintaining order only on first level? Is there any data structure that holds order in nested maps also? #171

Open
punithck opened this issue Aug 31, 2021 · 2 comments

Comments

@punithck
Copy link

https://play.golang.org/p/AIAkjs_TELp
If we see above example. linkedhashmap is maintaining the order only on firsl level of keys. It is not maintaining the same for nested keys or maps.
Do we have any data structure that holds order in nested keys also?

Input:

{"pulse_in_sec":60,"pulse_count":1,"rate":1.0,"slabs":["1-50"],"billplan_hierarchy":{"direction":"outgoing","legType":"pstn","callType":"trans","endUserCircleMask":"intra"}}

Expected:

map[pulse_in_sec:60 pulse_count:1 rate:1 slabs:[1-50] billplan_hierarchy:map[direction:outgoing legType:pstn  callType:trans endUserCircleMask:intra]]

Ouput:

map[pulse_in_sec:60 pulse_count:1 rate:1 slabs:[1-50] billplan_hierarchy:map[callType:trans direction:outgoing endUserCircleMask:intra legType:pstn]]
@emirpasic
Copy link
Owner

@punithck unfortunately there is no data structure that can go beyond the first level simply due to the randomness in iteration order of maps when unmarshalling JSON to map in Golang.

The only way to achieve this is to write GoDS own unmarshaler as was done in json/decode

Given this would be a cool feature to have in GoDS as there is nothing out there that can anything similar on the web in Golang, it would give GoDS more value.

Hence, I will keep this issue open until GoDS JSON decode is implemented to unmarshal JSON into GoDS' data structures.

@retrodaredevil
Copy link

FromJSON is actually more problematic than described above:

Take this unit test:

func TestGodsLinkedHashMapRetainsOrderWithComplexJSON(t *testing.T) {
	jsonString := `
{
  "a": 1,
  "c": {
    "b": 1,
    "a": 2,
    "c": 3
  },
  "d": 3,
  "b": 4
}
`
	data := linkedhashmap.New[string, any]()
	err := json.Unmarshal([]byte(jsonString), &data)
	if err != nil {
		t.Fatal("Could not unmarshal json", err)
		return
	}
	it := data.Iterator()
	it.Next()
	if it.Key() != "a" {
		t.Error("First key not a")
	}
	it.Next()
	if it.Key() != "c" {
		t.Error("Second key not c")
	}

	it.Next()
	if it.Key() != "d" {
		t.Error("Third key not d") // IT FAILS HERE
	}
	it.Next()
	if it.Key() != "b" {
		t.Error("Forth key not b") // And also here
	}
}

@punithck points out that the object won't have sorted fields (its value is of the type map[string]interface{}). However, this test shows that the keys d and b are put in the wrong order because the key b is present in nested JSON.

index[key] = bytes.Index(data, esc)
shows that the logic works by finding the index of the key in the JSON itself, which seems messy.

I bumped this issue because one of the reasons I looked into GoDS is because it's one of the few libraries with a linked hash map implementation that seems standard enough to use in production code. I was hoping it could be my solution to parsing arbitrary JSON and keeping the fields in the order they were in the JSON. So, I was wondering if there were any plans to implement a JSON parser so that the order would be correct for complex JSON objects like I showed in the above unit test, and so that nested JSON objects can have their fields ordered correctly.

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

No branches or pull requests

3 participants