解析没有已知结构的 TOML 文件。

huangapple go评论85阅读模式
英文:

parsing TOML without a known structure

问题

与这个关于rust的问题类似,我想解析一个TOML文件,但是对整个TOML结构没有很强的了解。所以,我根据这个reddit的讨论尝试了以下代码:

# Configuration of Server Control 
[config]
control_server_ipaddr = "0.0.0.0"
control_server_port = 7077

[[module]]
filename = "filename_test1"
execcmd = "execcmd_test1"

[[module]]
filename = "filename_test2"
execcmd = "execcmd_test2"
package main

import (
	"fmt"
	"github.com/BurntSushi/toml"
)

type tomlConfig struct {
	Conf map[string]any
}

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func main() {
	var c tomlConfig
	if _, err := toml.DecodeFile("config.toml", &c); err != nil {
		fmt.Println(err)
		return
	}

        fmt.Printf("%#v\n",c.Conf)

	for k, v := range c.Conf {
		fmt.Printf("%s\n", k)
		switch c := v.(type) {
    			case string:
        			fmt.Printf("Item %q is a string, containing %q\n", k, c)
    			case float64:
        			fmt.Printf("Looks like item %q is a number, specifically %f\n", k, c)
    			default:
        			fmt.Printf("Not sure what type item %q is, but I think it might be %T\n", k, c)
    		}
	}	
}

但是这样生成了一个空输出:

map[string]interface {}(nil)
英文:

Similar to this question for rust, I want to parse a TOML without having a strong knowledge of the entire structure of the TOML. So, my first attempt based on this reddit discussion was something like this:

# Configuration of Server Control 
[config]
control_server_ipaddr = "0.0.0.0"
control_server_port = 7077

[[module]]
filename = "filename_test1"
execcmd = "execcmd_test1"

[[module]]
filename = "filename_test2"
execcmd = "execcmd_test2"
package main

import (
	"fmt"
	"github.com/BurntSushi/toml"
)

type tomlConfig struct {
	Conf map[string]any
}

func check(e error) {
    if e != nil {
        panic(e)
    }
}

func main() {
	var c tomlConfig
	if _, err := toml.DecodeFile("config.toml", &c); err != nil {
		fmt.Println(err)
		return
	}

        fmt.Printf("%#v\n",c.Conf)

	for k, v := range c.Conf {
		fmt.Printf("%s\n", k)
		switch c := v.(type) {
    			case string:
        			fmt.Printf("Item %q is a string, containing %q\n", k, c)
    			case float64:
        			fmt.Printf("Looks like item %q is a number, specifically %f\n", k, c)
    			default:
        			fmt.Printf("Not sure what type item %q is, but I think it might be %T\n", k, c)
    		}
	}	
}

but that generated an empty output:

map[string]interface {}(nil)

答案1

得分: 1

作为一个可能的解决方案,我提供了以下代码:

package main

import (
	"os"
	"fmt"
	"github.com/BurntSushi/toml"
)

type tomlConfig struct {
	Conf map[string]interface{}
}

	
func check(e error) {
    if e != nil {
        panic(e)
    }
}


func isType(a, b interface{}) bool {
    return fmt.Sprintf("%T", a) == fmt.Sprintf("%T", b)
}


func PrintDict(k1 string, v1 interface{}) {
    fmt.Printf("Key:%s\n",k1)
    if isType(v1,  make(map[string]interface{})) {
        data := v1.(map[string]interface{})
        for k2, v2 := range data {
          PrintDict(k2, v2)
        }
    } else {
       fmt.Printf("Value:%s\n",v1)
    }
}


func main() {
	var Conf map[string]interface{}
        data, err := os.ReadFile("config.toml")
        if err != nil {
                fmt.Printf("ERROR: reading (config.toml).")
                os.Exit(1)
        }
        err=toml.Unmarshal(data, &Conf)

        for k, v := range Conf {
                PrintDict(k, v)
        }
}

对于生成的 config.toml 文件,它会输出以下内容:

Key:config
Key:control_server_ipaddr
Value:0.0.0.0
Key:control_server_port
Value:%!s(int64=7077)
Key:module
Value:[map[execcmd:execcmd_test1 filename:filename_test1] map[execcmd:execcmd_test2 filename:filename_test2]]
英文:

As a possible solution, I came up with was this below,

package main

import (
	"os"
	"fmt"
	"github.com/BurntSushi/toml"
)

type tomlConfig struct {
	Conf map[string]any
}

	
func check(e error) {
    if e != nil {
        panic(e)
    }
}


func isType(a, b interface{}) bool {
    return fmt.Sprintf("%T", a) == fmt.Sprintf("%T", b)
}


func PrintDict(k1 string, v1 interface{}) {
    fmt.Printf("Key:%s\n",k1)
    if isType(v1,  make(map[string]any)) {
        data := v1.(map[string]interface{})
        for k2, v2 := range data {
          PrintDict(k2, v2)
        }
    } else {
       fmt.Printf("Value:%s\n",v1)
    }
}


func main() {
	var Conf map[string]any
        data, err := os.ReadFile("config.toml")
        if err != nil {
                fmt.Printf("ERROR: reading (config.toml).")
                os.Exit(1)
        }
        err=toml.Unmarshal(data, &Conf)

        for k, v := range Conf {
                PrintDict(k, v)
        }
}

for the config.toml it generated the following output:

Key:config
Key:control_server_ipaddr
Value:0.0.0.0
Key:control_server_port
Value:%!s(int64=7077)
Key:module
Value:[map[execcmd:execcmd_test1 filename:filename_test1] map[execcmd:execcmd_test2 filename:filename_test2]]

huangapple
  • 本文由 发表于 2023年6月5日 03:30:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/76402098.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定