如何将字符串编码的浮点数数组解组为浮点数数组



我试图解组一些json数据,我从一个web服务。我简化了这个问题,如下面的代码所示。我的问题是我可以使版本(c)在代码工作…

我知道它适用于单个数字值,如"时间戳"所示,通过添加选项",字符串"到json注释。但我不能弄清楚如何或如果这也适用于字符串编码的数字数组。(参见代码中列出的示例json中的"conversions")

package main
import (
    "encoding/json"
    "fmt"    
)
//version (a)
type JsonData1 struct {
    TimeStamp   uint64          `json:"timestamp,string"`
    Conversions [][2]string     `json:"conversions"`
}
//version (b)
type JsonData2 struct {
    TimeStamp   uint64              `json:"timestamp,string"`
    Conversions [][2]json.Number    `json:"conversions"` 
}
//version (c)
type JsonData3 struct {
    TimeStamp   uint64          `json:"timestamp,string"`
    Conversions [][2]float32    `json:"conversions"` 
}
const incomingJson string = `{"timestamp": "1407178369", "conversions": [["1.021", "2.124"], ["2.432", "3.923"], ["3.234", "5.001"]]}`
func main() {
    var data1 JsonData1
    if err1 := json.Unmarshal([]byte(incomingJson), &data1); err1 != nil {
        fmt.Println("Error unmarshaling with struct JsonData1")
        fmt.Println("--> ", err1.Error())
    } else {
        fmt.Println("Success unmarshaling with struct JsonData1")
        fmt.Println("--> ", data1)
    }
    var data2 JsonData2
    if err2 := json.Unmarshal([]byte(incomingJson), &data2); err2 != nil {
        fmt.Println("Error unmarshaling with struct JsonData2")
        fmt.Println("--> ", err2.Error())
    } else {
        fmt.Println("Success unmarshaling with struct JsonData2")
        fmt.Println("--> ", data2)
    }    
    var data3 JsonData3
    if err3 := json.Unmarshal([]byte(incomingJson), &data3); err3 != nil {
        fmt.Println("Error unmarshaling with struct JsonData3")
        fmt.Println("--> ", err3.Error())
    } else {
        fmt.Println("Success unmarshaling with struct JsonData3")
        fmt.Println("--> ", data3)
    }  
}

如果我编译并运行代码,我得到这样的输出:

Success unmarshaling with struct JsonData1
-->  {1407178369 [[1.021 2.124] [2.432 3.923] [3.234 5.001]]}
Success unmarshaling with struct JsonData2
-->  {1407178369 [[1.021 2.124] [2.432 3.923] [3.234 5.001]]}
Error unmarshaling with struct JsonData3
-->  json: cannot unmarshal string into Go value of type float32

您可以在这里运行代码:http://play.golang.org/p/4TC0IgCI8H

是否有一种方法来实现反编组到结构版本(c)?谢谢你的帮助!

我知道要做到这一点最简单的方法是定义一个新的类型,然后为它定义UnmarshalJSON:

type Conversions [][2]float64
func (c *Conversions) UnmarshalJSON(b []byte) error {
    tmp := [][2]json.Number{}
    if err := json.Unmarshal(b, &tmp); err != nil {
        return err
    }
    *c = make(Conversions, len(tmp))
    for i, a := range tmp {
        var (
            pair [2]float64
            err  error
        )
        pair[0], err = a[0].Float64()
        if err != nil {
            return err
        }
        pair[1], err = a[1].Float64()
        if err != nil {
            return err
        }
        (*c)[i] = pair
    }
    return nil
}

Playground,见版本(d)。这不是最完美的方法,算法可以改进以使用更少的资源,但你明白了。

您不能这样做,因为您将它们作为字符串传递,您最好的选择是使用json.Number并编写如下函数:

func fval(n json.Number) float32 {
    if f, err := n.Float64(); err == nil {
        return float32(f)
    }
    return 0
}
.....
f := fval(data2.Conversions[0][0])

如果在数字周围加上",它们就被认为是字符串。事实上,在前两种结构中你没有任何问题。

如果你想把它们转换成数字类型,使用正确的方法:parse float

这里你可以看到如何使用ParseFloat: http://play.golang.org/p/XDuiF0FCQq

最新更新