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

How to unmarshal map[string]map[string]interface{} #337

Closed
se7entyse7en opened this issue Mar 14, 2020 · 5 comments
Closed

How to unmarshal map[string]map[string]interface{} #337

se7entyse7en opened this issue Mar 14, 2020 · 5 comments
Labels
question Question from a go-toml user.

Comments

@se7entyse7en
Copy link

se7entyse7en commented Mar 14, 2020

Describe the bug
This is more a question. How can I properly unmarshal a toml as the following?

[tool.pydockenv]
name = "jupyter-notebook"
python = "3.7.4"

[tool.pydockenv.dependencies]
jupyter = "==1.0.0"

[tool.pydockenv.aliases]

[tool.pydockenv.aliases.notebook]
cmd = "jupyter notebook --allow-root --ip=0.0.0.0 --port=8888"
ports = [8888]

where there's no fixed structure for tool.pydockenv.aliases.

To Reproduce

type Config struct {
	Name          string
	Python        string
	ProjectDir    string
	Dependencies  map[string]string
	ContainerArgs map[string]string
	Aliases       map[string]map[string]interface{}
}

type RawConfig struct {
	Tool struct {
		Pydockenv *Config
	}
}

doc := []byte(`
[tool.pydockenv]
name = "jupyter-notebook"
python = "3.7.4"

[tool.pydockenv.dependencies]
jupyter = "==1.0.0"

[tool.pydockenv.aliases]

[tool.pydockenv.aliases.notebook]
cmd = "jupyter notebook --allow-root --ip=0.0.0.0 --port=8888"
ports = [8888]`)

rawConfig := environment.RawConfig{}
toml.Unmarshal(doc, &rawConfig)
fmt.Println("name=", rawConfig.Tool.Pydockenv.Name)
fmt.Println("aliases=", rawConfig.Tool.Pydockenv.Aliases)

This doesn't work as it raises:

panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x0 pc=0x148e9b4]

at the line with where it should print the name.

If I change it to:

doc := []byte(`
[tool.pydockenv]
name = "jupyter-notebook"
python = "3.7.4"

[tool.pydockenv.dependencies]
jupyter = "==1.0.0"`)

then it assigns the name correctly, so I guess something is wrong in the Aliases field of Config. Here's the output:

name= jupyter-notebook
aliases= map[]

By using the original doc value, I also tried to change the Config as follows:

type Config struct {
	Name          string
	Python        string
	ProjectDir    string
	Dependencies  map[string]string
	ContainerArgs map[string]string
	Aliases       map[string]struct {
		Notebook struct {
			Cmd   string
			Ports []int
		}
	}
}

but the aliases is not there:

name= jupyter-notebook
aliases= map[]

Versions

  • go-toml: v1.2.0
  • go: go version go1.14
  • operating system: macOS
@se7entyse7en
Copy link
Author

To give more context the key of aliases can be any string, but the values are always cmd and ports, so for example:

[tool.pydockenv.aliases]

[tool.pydockenv.aliases.notebook1]
cmd = "jupyter notebook --allow-root --ip=0.0.0.0 --port=8888"
ports = [8888]`

[tool.pydockenv.aliases.notebook2]
cmd = "jupyter notebook --allow-root --ip=0.0.0.0 --port=8080"
ports = [8080]`

@se7entyse7en
Copy link
Author

I also tried:

type Config struct {
	Name          string
	Python        string
	ProjectDir    string
	Dependencies  map[string]string
	ContainerArgs map[string]string
	Aliases       map[string]interface{}
}

type RawConfig struct {
	Tool struct {
		Pydockenv *Config
	}
}

doc := []byte(`
[tool.pydockenv]
name = "jupyter-notebook"
python = "3.7.4"

[tool.pydockenv.dependencies]
jupyter = "==1.0.0"

[tool.pydockenv.aliases]

[tool.pydockenv.aliases.notebook]
cmd = "jupyter notebook --allow-root --ip=0.0.0.0 --port=8888"
ports = [8888]`)

rawConfig := environment.RawConfig{}
toml.Unmarshal(doc, &rawConfig)
fmt.Println(rawConfig)

but it prints {{<nil>}}.

But maybe this is solved by #335 ?

@AllenX2018
Copy link
Contributor

AllenX2018 commented Mar 16, 2020

I look into the implementation of unmarshal and find that it seems go-toml do not support interface{} field unmarshalling for now. It need to be fixed. But for your case, I try:

	type Config struct {
		Name          string
		Python        string
		ProjectDir    string
		Dependencies  map[string]string
		ContainerArgs map[string]string
		Aliases       map[string]struct {
			Cmd   string
			Ports []int
		}
	}
	type RawConfig struct {
		Tool struct {
			Pydockenv *Config
		}
	}

	doc := []byte(`
[tool.pydockenv]
name = "jupyter-notebook"
python = "3.7.4"

[tool.pydockenv.dependencies]
jupyter = "==1.0.0"

[tool.pydockenv.aliases]

[tool.pydockenv.aliases.notebook]
cmd = "jupyter notebook --allow-root --ip=0.0.0.0 --port=8888"
ports = [8888]`)

	rawConfig := RawConfig{}
	if err := toml.Unmarshal(doc, &rawConfig); err != nil {
		fmt.Println(err)
	}

	fmt.Println("name=", rawConfig.Tool.Pydockenv.Name)
	fmt.Println("aliases=", rawConfig.Tool.Pydockenv.Aliases)

And it works in my environment(with latest version v1.6.0). Just change Aliases from map[string]map[string]interface{} to map[string]struct, but you don't need the Notebook part. Maybe you can try this as a workround.

@se7entyse7en
Copy link
Author

Thanks a lot @AllenX2018! This is exactly what I was looking for!

@pelletier pelletier added the question Question from a go-toml user. label Mar 17, 2020
@pelletier
Copy link
Owner

Awesome, glad you got unblocked! Thank you @AllenX2018. Unfortunately yes, the diagnostic is correct: support for map[.]interface{} has not been implemented yet. Issue #150 is the main one for that work.
Closing this issue, but feel free to re-open if you need anything else!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
question Question from a go-toml user.
Projects
None yet
Development

No branches or pull requests

3 participants