如何在golang中轻松编辑JSON类型(如Node.js)

TH *_*Cho 5 json go node.js hyperledger-fabric

我尝试将 node.js 代码转换为 golang 代码。

这是我的示例 JSON。

{
  "result": {
    "birthInfo": {
      "birthYmd": "2018-07-25",
      "cattleNo": "cow001",
      "docType": "registerBirth",
      "lsTypeNm": "redbull",
      "monthDiff": "2018-07",
      "nationNm": "japan",
      "regType": "directly",
      "regYmd": "2018-07-25",
      "sexNm": "farm001"
    },
    "breed": {
      "dead": {
        "deadCd": "deadcd20180725",
        "deadYmd": "2018-07-25",
        "docType": "reportDeCattle"
      },
      "earTag": {
        "docType": "reattachEartag",
        "flatEartagNo": "eartag206015",
        "rfidNo": "rfid234234"
      }
    }
  }
}  
Run Code Online (Sandbox Code Playgroud)

使用node.js时,可以很容易地获取或访问这样的json数据。

let cowbytes = await stub.getState("cow001");
var cowInfo = JSON.parse(cowbytes);

var eartag = {
  docType: 'reattachEartag',
  flatEartagNo: "eartag206015",
  rfidNo: "rfid234234",
};

if (cowInfo.breed) {
  cowInfo.breed['earTag'] = eartag;
} else {
  cowInfo.breed = {
    earTag: eartag
  };
}

await stub.putState(args[0], Buffer.from(JSON.stringify(cowInfo)));
Run Code Online (Sandbox Code Playgroud)

这是我的 golang 代码,我对 Node.js 代码进行了基准测试。

cowbytes, _: = APIstub.GetState("cow001")
if cowbytes == nil {
  return shim.Error("Incorrect value. No cattle Info..")
}

var cowInfo map[string] interface {}
json.Unmarshal(cowbytes, & cowInfo)
eartag: = make(map[string] interface {})

eartag["docType"] = "reattachEartag"
eartag["flatEartagNo"] = string("eartag206015")
eartag["rfidNo"] = string("rfid234234")


_, exists: = cowInfo["breed"]
if exists {
  inputJSON,
  err: = json.Marshal(cowInfo["breed"])
  fmt.Println(err)
  out: = map[string] interface {} {}
  json.Unmarshal([] byte(inputJSON), & out)
  out["earTag"] = struct {
    EarTag map[string] interface {}
    `json:"earTag"`
  } {
    eartag,
  }
  cowInfo["breed"] = out

}
else {
  cowInfo["breed"] = struct {
    EarTag map[string] interface {}
    `json:"earTag"`
  } {
    eartag,
  }
}

cattleAsBytes, _: = json.Marshal(cowInfo)
APIstub.PutState(string("cow001"), cattleAsBytes)    
Run Code Online (Sandbox Code Playgroud)

虽然我的golang文件工作正常,但我认为它不仅很难编写代码而且性能也很差(重复编组和解组)。

如何轻松控制 Golang 中的 JSON 类型。

有人有想法吗?

icz*_*cza 4

您通常必须在性能和简单性之间做出选择。

如果您需要性能,请使用结构对 JSON 输入进行建模,然后您可以使用结构上的选择器轻松获取/设置不同的部分,并且您还可以免费获得 Go 的类型安全性。注意:有一些库和在线服务可以根据输入的 JSON 文本自动生成 Go 结构,例如https://mholt.github.io/json-to-go/。

如果您选择简单性,则可以使用允许轻松操作“动态”对象的第 3 方库(例如,映射和切片,它们是解组此类 JSON 输入文本的结果)。

其一,有github.com/icza/dyno(披露:我是作者)。

使用dyno,解决方案的简单性接近于 JavaScript 的解决方案。由于dyno在地图和切片上进行操作,因此对于某些任务来说它可能会更慢,但是对于您问题中的这种简单任务,它可能会更快,因为它不使用反射(仅类型断言和类型开关)。

假设标识符src保存您输入的 JSON 文本(可以是常量或变量),那么与您的等效的 Go 代码是:

var cowInfo interface{}
if err := json.Unmarshal([]byte(src), &cowInfo); err != nil {
    panic(err)
}

eartag := map[string]string{
    "docType":      "reattachEartag",
    "flatEartagNo": "eartag206015",
    "rfidNo":       "rfid234234",
}

if breed, err := dyno.Get(cowInfo, "result", "breed"); err == nil {
    dyno.Set(breed, eartag, "earTag")
} else {
    dyno.Set(cowInfo, map[string]interface{}{"earTag": eartag}, "result", "breed")
}

enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", "  ")
if err := enc.Encode(cowInfo); err != nil {
    panic(err)
}
Run Code Online (Sandbox Code Playgroud)

上面的代码解组输入 JSON,执行处理/修改,最后将结果编组到控制台。

这是完整的应用程序:Go Playground。注意:你不能在 Go Playground 上运行它,因为它是导入的github.com/icza/dyno(并且那里不允许导入第 3 方库),你必须在本地运行它(在 go getting 之后dyno)。