duanrenzou1619 2013-10-30 18:53
浏览 49
已采纳

JSON解码具有灵活的类型

I need to specify a type for decoding JSON data in a flexible manner, meaning the type needs to be specified at runtime.

Consider this snippet: http://play.golang.org/p/F-Jy4ufMPz

s := `{"b":[{"x":9},{"x":4}]}`

var a struct {
  B []interface{}
}
err := json.Unmarshal([]byte(s), &a)
if err != nil {
  panic(err)
}

fmt.Println(a)

Which will produce {[map[x:9] map[x:4]]}. I want to decode to an array of a specific (struct) type instead of []interface{}, without specifying it at compile time.

Is that somehow possible without creating the array up front? (the number of returned items is unknown)

The only way I can think of right now is to encode the returned maps again later, and decode them to the specified type, which would create unnecessary processing overhead.

  • 写回答

1条回答 默认 最新

  • doudou3213 2013-10-30 20:19
    关注

    If not specifying it at compile time, you still need to specify it somewhere.

    If specified before the retrieval of the Json data, you can simply do a switch case, Unmarshalling it to your desired object.

    If specified within the Json data, you can marshal the "flexible" part into a json.RawMessage to process it after you've decided what type of struct is suitable:

    package main
    
    import (
        "encoding/json"
        "fmt"
    )
    
    var s = `{"type":"structx", "data":{"x":9,"xstring":"This is structX"}}`
    
    type JsonStruct struct {
        Type string
        Data json.RawMessage
    }
    
    type StructX struct {
        X       float64
        Xstring string
    }
    
    type StructY struct {
        Y bool
    }
    
    func main() {
        var a *JsonStruct
        err := json.Unmarshal([]byte(s), &a)
        if err != nil {
            panic(err)
        }
    
        switch a.Type {
        case "structx":
            // We Unmashal the RawMessage part into a StructX
            var s *StructX
            json.Unmarshal([]byte(a.Data), &s)
            if err != nil {
                panic(err)
            }
            fmt.Println(s)
        case "structy":
            // Do the same but for structY
        }
    }
    

    Playground

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 深度学习中的画图问题
  • ¥15 java报错:使用mybatis plus查询一个只返回一条数据的sql,却报错返回了1000多条
  • ¥15 Python报错怎么解决
  • ¥15 simulink如何调用DLL文件
  • ¥15 关于用pyqt6的项目开发该怎么把前段后端和业务层分离
  • ¥30 线性代数的问题,我真的忘了线代的知识了
  • ¥15 有谁能够把华为matebook e 高通骁龙850刷成安卓系统,或者安装安卓系统
  • ¥188 需要修改一个工具,懂得汇编的人来。
  • ¥15 livecharts wpf piechart 属性
  • ¥20 数学建模,尽量用matlab回答,论文格式