Json 键入assert接口以在Go中映射的更好方法

Json 键入assert接口以在Go中映射的更好方法,json,dictionary,go,interface,type-assertion,Json,Dictionary,Go,Interface,Type Assertion,我将JSON存储在一个包含嵌套对象的文件中 结构如下所示: { "users" : { "enxtropayy": { "pass": "", "root": true, "admin": true, "moderator": true } } } var data interface

我将JSON存储在一个包含嵌套对象的文件中

结构如下所示:

{
  "users" : {
    "enxtropayy": {
      "pass": "",
      "root": true,
      "admin": true,
      "moderator": true
    }
  }
}
var data interface{}
json.Unmarshal(usr,&data)
fmt.Println(data.(interface{}).(map[string]interface{})["users"].(interface{}).(map[string]interface{})["enxtropayy"])
Soooo,我希望能够通过Go访问“enxtropayy”用户:

usr, _ := ioutil.ReadFile("userInfo.JSON")
var data map[string]interface{}
json.Unmarshal(usr,&data)
fmt.Println(data["users"])
它打印
map[enxtropayy:map[admin:true版主:true通行证:root:true]

这很好,但我只能深入到一层,我发现这是因为接口没有键

因此,我重新编写了Go代码,如下所示:

{
  "users" : {
    "enxtropayy": {
      "pass": "",
      "root": true,
      "admin": true,
      "moderator": true
    }
  }
}
var data interface{}
json.Unmarshal(usr,&data)
fmt.Println(data.(interface{}).(map[string]interface{})["users"].(interface{}).(map[string]interface{})["enxtropayy"])
它起作用了!但是,每次我想访问另一个嵌套层时,我都必须执行
(映射[string]接口{})[“keyName”]
,这看起来不是很“整洁”,编写起来有点乏味。这似乎也没有必要,而且可能不是最佳做法。整个“类型断言”和“接口/映射”对我来说都是新的,所以我不知道我在做什么,这是我想要改进的


有没有其他方法可以为映射输入assert接口(或者更好的方法将JSON存储在Go中),您也可以解释一下它的工作原理(给一个人一条鱼,他可以吃一天;教一个人钓鱼,他可以吃一天)?

如果可能的话,最好只使用
struct

package main

import (
   "encoding/json"
   "fmt"
)

const s = `
{
   "users" : {
      "enxtropayy": {
         "admin": true, "moderator": true, "root": true,
         "pass": ""
      }
   }
}
`

func main() {
   var t struct {
      Users map[string]struct {
         Admin, Moderator, Root bool
         Pass string
      }
   }
   json.Unmarshal([]byte(s), &t)
   // {Users:map[enxtropayy:{Admin:true Moderator:true Root:true Pass:}]}
   fmt.Printf("%+v\n", t)
}

为了避免在读取json解组的数据对象时出现常量类型断言,最好定义一个模仿json结构的Go结构,并将其解组,而不是使用
map[string]接口{}
。如果您不能依赖JSON数据的结构,那么在使用它们之前,您当然需要断言事物的类型(并且应该检查断言是否使用逗号ok模式失败)。@HymnsForDisco听起来不错!我将尝试找出如何使结构具有动态结构(因为JSON将在将来更改以分配更多用户)。您不能具有动态结构,但如果只有用户在更改,则可能是,例如,
map[string]UserInfo
,使每个用户的结构都是静态的,但用户列表是动态的。这正是我想做的事情!我必须研究一下如何做到这一点。围棋在我所知道的其他语言中是如此的怪异,以至于它几乎与我所知道的背道而驰。这很清楚地消除了我在评论中对如何执行建议策略的怀疑。谢谢但是有一个问题,我无法编辑
Pass
值。有没有办法直接改变这个?哦,等等,修好了!解决方案:把传球变成一个指针,然后直接引用它(哇,我真不敢相信这有多容易)@事实上,我猜这可能会有所帮助。如果没有,请寻找其他问题或提出新问题。(哎呀,你已经明白了。)@HymnsForDisco谢谢(我得出了与其中一个答案相同的结论)!有时我必须记住,我有一个大脑,可以使用它。我已经使用了足够多的指针来理解它们,但我仍然感到惊讶。是的,
json
包非常聪明,它使用反射来确定如何将值适当地存储到结构中,即使使用指针与正常值。另一个选项是使用类似于
map[string]*UserInfo
的模式,以便在需要时更新所有字段。