Golang中如何将字符串转换为JSON键进行访问

Golang中如何将字符串转换为JSON键进行访问 我有一个映射(字符串),用于将“标签”转换为文本中的“词语” 这个“标签”列表必须被来自某个结构体的值所替换

示例:

var users struc {
login String `json:" options "`
passwd String `json:" options "`
}
var folders struc {
arch String `json:" folders "`
dest String `json:" folders "`
}
var TAGS = map [string] string {
"{login}": "users.login",
"{passwd}": "users.passwd",
"{archive}": "folders.arch",
"{dest}": "folders.dest",
}

类似这样:

var test = "Name = {login} archive = {archive} destination = {dest} / {login}"
var realTest = ReplaceTag (test, &TAGS)

我不知道如何将值中的字符串转换为结构体的实际值。 我知道如何直接操作,但当它以字符串形式存在时就不知道了。

我创建了一个“Go Playground”以便更清晰地说明https://play.golang.org/p/qhmYnwiB5NO

提前感谢


更多关于Golang中如何将字符串转换为JSON键进行访问的实战教程也可以访问 https://www.itying.com/category-94-b0.html

5 回复

所以你的问题是如何实现 ReplaceTag 来将

"Name = {login} archive = {archive} destination = {dest} / {login}"

转换为

"Name = users.login archive = folders.arch destination = folders.dest / users.login"

我理解得对吗?foldersusers 是做什么用的?

更多关于Golang中如何将字符串转换为JSON键进行访问的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


这非常“像eval”。Go语言没有类似eval的函数。你可以使用这样的函数来实现类似功能:https://play.golang.org/p/mFsFrVAQjG_I,或者也可以使用模板:https://play.golang.org/p/bjHovjaoR7W

太棒了!非常感谢。

我稍微修改了一下,但原理是一样的,它可以工作。

var TAGS = map[string]string{
    "{login}":   "Users.Login",
    "{passwd}":  "Users.Passwd",
    "{archive}": "Folders.Archive",
    "{dest}":    "Folders.Destination",
}

func main() {
    conf := config{}
    json.Unmarshal(jsonData, &conf)

    var buf bytes.Buffer
    for tag, value := range TAGS {
        template.Must(template.New("").Parse("{{."+value+"}}")).Execute(&buf, conf)
        TestString = strings.ReplaceAll(TestString, tag, string(buf.Bytes()))
        buf.Reset()
    }
    fmt.Println(TestString)
}

不完全是这样。 我想用结构的 来替换。结构体本身反映了 JSON 文件的结果。

我创建了一个“Go Playground”来更清楚地说明:Go Playground - The Go Programming Language

注意: 如果我在 main() 中像这样使用“TAG”映射,这是可行的:

TAGS := map[string]string{
        "{login}":   conf.Users.Login,
        "{passwd}":  conf.Users.Passwd,
        "{archive}": conf.Folders.Archive,
        "{dest}":    conf.Folders.Destination,
    }

但是我需要在其他地方使用这个映射,所以我必须将其声明为全局变量。

在 PHP 中,我们可以这样做:

$Bar = "a";
$Foo = "Bar";
$World = "Foo";
$Hello = "World";
$a = "Hello";

$a; //返回 Hello
$$a; //返回 World
$$$a; //返回 Foo
$$$$a; //返回 Bar
$$$$$a; //返回 a

谢谢

在Go中,你可以使用反射(reflection)来根据字符串路径访问结构体的字段。以下是一个完整的解决方案:

package main

import (
	"fmt"
	"reflect"
	"strings"
)

type Users struct {
	Login  string `json:"options"`
	Passwd string `json:"options"`
}

type Folders struct {
	Arch string `json:"folders"`
	Dest string `json:"folders"`
}

var TAGS = map[string]string{
	"{login}":    "users.login",
	"{passwd}":   "users.passwd",
	"{archive}":  "folders.arch",
	"{dest}":     "folders.dest",
}

func getFieldValue(path string, data map[string]interface{}) string {
	parts := strings.Split(path, ".")
	if len(parts) != 2 {
		return ""
	}

	objName := parts[0]
	fieldName := parts[1]

	if obj, ok := data[objName]; ok {
		val := reflect.ValueOf(obj)
		if val.Kind() == reflect.Ptr {
			val = val.Elem()
		}

		field := val.FieldByName(strings.Title(fieldName))
		if field.IsValid() && field.Kind() == reflect.String {
			return field.String()
		}
	}
	return ""
}

func ReplaceTag(text string, tags map[string]string, data map[string]interface{}) string {
	result := text
	for tag, path := range tags {
		value := getFieldValue(path, data)
		result = strings.ReplaceAll(result, tag, value)
	}
	return result
}

func main() {
	users := &Users{
		Login:  "john_doe",
		Passwd: "secret123",
	}

	folders := &Folders{
		Arch: "/backup",
		Dest: "/archive",
	}

	data := map[string]interface{}{
		"users":   users,
		"folders": folders,
	}

	var test = "Name = {login} archive = {archive} destination = {dest} / {login}"
	var realTest = ReplaceTag(test, TAGS, data)
	fmt.Println(realTest)
	// 输出: Name = john_doe archive = /backup destination = /archive / john_doe
}

如果你需要处理嵌套更深的结构体路径,可以使用这个更通用的版本:

func getFieldValueByPath(path string, data map[string]interface{}) string {
	parts := strings.Split(path, ".")
	if len(parts) < 2 {
		return ""
	}

	objName := parts[0]
	fieldPath := parts[1:]

	if obj, ok := data[objName]; ok {
		val := reflect.ValueOf(obj)
		if val.Kind() == reflect.Ptr {
			val = val.Elem()
		}

		for _, fieldName := range fieldPath {
			if val.Kind() != reflect.Struct {
				return ""
			}
			field := val.FieldByName(strings.Title(fieldName))
			if !field.IsValid() {
				return ""
			}
			val = field
		}

		if val.Kind() == reflect.String {
			return val.String()
		}
	}
	return ""
}

这个解决方案的关键点:

  1. 使用反射包(reflect)来动态访问结构体字段
  2. 将结构体实例存储在map中以便按名称查找
  3. 通过FieldByName方法根据字段名获取值
  4. 注意处理指针类型和字段名的首字母大写(Go的导出字段要求)
  5. 使用strings.ReplaceAll进行标签替换
回到顶部