为了账号安全,请及时绑定邮箱和手机立即绑定

在golang中使用未知结构的json对象有更简洁的方法吗?

在golang中使用未知结构的json对象有更简洁的方法吗?

Go
慕哥6287543 2021-11-15 20:52:11
当我有一个可靠的 rest api 端点返回一些简单的 json 时,我可以使用结构来准确定义预期 json 结果的结构,但是我必须使用某些端点来返回非常大且复杂的 json 结果数据,并且这些结果的结构并不总是已知的。我一直在使用它来解组:type JsonObj map[string]interface{}func (jo JsonObj) GetString(name string) (string, error) {    if val, exists := jo[name]; exists {        if v, ok := val.(string); ok {            return v, nil        }        return "", errors.New(name+" is not a string")    }    return "", errors.New(name+" property not found")}func (jo JsonObj) GetFloat64(name string) (float64, error) {    if val, exists := jo[name]; exists {        if v, ok := val.(float64); ok {            return v, nil        }        return 0, errors.New(name+" is not a float64")    }    return 0, errors.New(name+" property not found")}以同样的方式我有GetInt, GetBool, GetSlice, GetJsonObj,但是正如您所看到的,除了类型断言参数之外,所有这些函数的内容几乎相同。有没有办法传入类型断言参数以将所有这些函数有效地减少为单个函数?
查看完整描述

1 回答

?
九州编程

TA贡献1785条经验 获得超4个赞

这是我现在最好的,作为一个非常简单的例子:https : //play.golang.org/p/U9WJ0bIJPp 我无法想象你能够压缩/提取它比这更多:


package main


import (

    "fmt"

    "errors"

)


type T interface{}

type JsonObj map[string]T


func (jo JsonObj) Type(name string, defaultVal T, typeName string, typeAsserter func(val T) (T, bool)) (T, error){

    if val, exists := jo[name]; exists {

        if v, ok := typeAsserter(val); ok {

            return v, nil

        }

        return defaultVal, errors.New(name+" is not of type "+typeName)

    }

    return defaultVal, errors.New(name+" property not found")

}


func (jo JsonObj) String(name string) (string, error) {

    ret, err := jo.Type(name, "", "string", func(val T)(ret T, ok bool){ret, ok = val.(string);return})

    return ret.(string), err

}


func (jo JsonObj) Float64(name string) (float64, error) {

    ret, err := jo.Type(name, 0, "float64", func(val T)(ret T, ok bool){ret, ok = val.(float64);return})

    return ret.(float64), err

}


func (jo JsonObj) Int(name string) (int, error) {

    ret, err := jo.Type(name, 0, "int", func(val T)(ret T, ok bool){if ret, ok = val.(float64); ok {ret = int(ret.(float64))};return})

    return ret.(int), err

}


func (jo JsonObj) Bool(name string) (bool, error) {

    ret, err := jo.Type(name, false, "bool", func(val T)(ret T, ok bool){ret, ok = val.(bool);return})

    return ret.(bool), err

}


func main() {

    jo := JsonObj{

        "aString": "foo",

        "aFloat64": 3.142,

        "anInt": 42.0, //in a json string unmarshalling all numbers are float64 even "int"s

        "aBool": true,


    }

    fmt.Println(jo.String("aString"))

    fmt.Println(jo.Float64("aFloat64"))

    fmt.Println(jo.Int("anInt"))

    fmt.Println(jo.Bool("aBool"))

    fmt.Println(jo.String("missingString"))

    fmt.Println(jo.Bool("anInt"))

}

但正如评论中提到的,有一个库提供了一种更强大的处理任意 json 的方法,https://github.com/bitly/go-simplejson


查看完整回答
反对 回复 2021-11-15
  • 1 回答
  • 0 关注
  • 266 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信