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

时间:2014-08-07 13:41:22

标签: arrays json go numbers unmarshalling

我正在尝试解组从Web服务获得的一些json数据。我已经简化了下面代码中显示的问题。我的问题是我可以在代码工作中制作版本(c)..

我知道它适用于单个数字值,如“timestamp”所示,方法是在json注释中添加选项“,string”。但我无法弄清楚这是如何或是否适用于字符串编码数字的数组。 (参见代码中列出的示例json中的“转换”)

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

有没有办法实现对struct version(c)的解组?谢谢你的帮助!

3 个答案:

答案 0 :(得分:5)

我知道这样做最简单的方法是定义一个新类型,然后为它定义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)。这不是最完美的方法,可以改进算法以减少资源使用,但你明白了。

答案 1 :(得分:0)

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

如果您想将它们转换为数字类型,请使用正确的方法执行此操作:parse float

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

答案 2 :(得分:0)

你不能这样做,因为你把它们作为字符串传递,你最好的选择是使用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])