go - 使用 reflect 遍历 go struct 字段与 case map[string]interface{} 不匹配

标签 go

我有一个不寻常的任务: 1. 将json消息解析为Go struct 2. 验证 JSON 中的所有字段是否在特定限制内: - 字符串字段长度不再固定不变 - map 包含的元素不超过固定数量 - 如果映射键的值是嵌套结构,则验证以上 2 条规则

为此,我使用反射,然后遍历元素, 并进行类型检查: - 如果是 int 或 float - 无事可做 - 无验证 - 如果是字符串 - 验证长度(如果失败则返回) - 如果 map 验证 map 长度(如果失败则返回),然后迭代 map 值并递归检查它们的字段是否违反 string/map 规则 - 默认(我假设这是 struct 嵌套的 JSON 结构):将其转换为接口(interface) slice 并进行递归调用。

问题: 在 JSON 中,我会有不同的映射值类型,例如: - map [字符串]MyStruct1 - map [字符串]MyStruct2 - 等

所以当我进行类型检查时,我写: 案例映射[字符串]接口(interface){}

但在我的程序中,这种情况永远不会匹配并进入默认情况, 导致一些错误。

将类型与大小写匹配的任何可能方法 - map[string]interface{} ????

这是我的引用代码: http://play.golang.org/p/IVXHLBRuPK

func validate(vals []interface{}) bool {
result := true
    for _, elem := range vals {
        switch v := elem.(type) {
        case int, float64:
            fmt.Println("Got int or float: ", v)
        case string:
            fmt.Println("Got string", v)
            if len(elem.(string)) > 5 {
                fmt.Println("String rule Violation!")
                result = false
                break
                fmt.Println("After Break")
            }
        case map[string]interface{}:
            fmt.Println("Got map", v)
            if len(elem.(map[string]interface{})) > 1 || !validate(elem.([]interface{})) {
                fmt.Println("Map length rule Violation!")
                result = false
                break
            }
        default:
            fmt.Println("Got struct:", v)

            // Convert to interface list all other structures no string/int/float/map:
            new_v := reflect.ValueOf(elem)
            new_values := make([]interface{}, new_v.NumField())
            for j := 0; j < new_v.NumField(); j++ {
                new_values[j] = new_v.Field(j).Interface()
            }

            // Recursively call for validate nested structs
            if !validate(new_values) {
                result = false
                break
            }
        }
    }
    fmt.Println("After Break 2")
    return result
}



func main() {
// Test truct:
x := C{1, B{"abc", A{10, 0.1, map[string]Host{"1,2,3,4": Host{"1.2.3.4"}}}}}

// Conversion:
v := reflect.ValueOf(x)
values := make([]interface{}, v.NumField())
for i := 0; i < v.NumField(); i++ {
    values[i] = v.Field(i).Interface()
}

// Validate function verification
fmt.Println(validate(values))
}

在这个例子中,我永远无法达到 case: map[string]interface{}

对有用的建议表示高度赞扬!

最佳答案

问题是 case map[string]interface{}map[string]Host 不匹配,所以它会被解析为一个结构,但它不是

您要么必须检查 new_v.Kind() 并通过反射处理 map ,要么为 map[string]Host 添加一个特殊情况。

关于go - 使用 reflect 遍历 go struct 字段与 case map[string]interface{} 不匹配,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33947944/

相关文章:

go - 我可以在 slice 中内联声明接口(interface)列表吗?

Golang 依赖管理最佳实践

go - Rbac 使用 Kubebuilder 进行规则

Golang 无法杀死子进程的父进程

go - 如何使用 context.Context 与 tcp 连接读取

url - 从 URL 中提取不区分大小写的查询参数

go - 如何在实时输出的同时将命令的标准输出和标准错误重定向到控制台和日志文件?

go - 仅在 kubernetes/CoreOS 上的 Go 中无效的 header 字段值

go - Go中结构本身的方法

unit-testing - 在 Golang 中 stub 函数