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

I'm trying to unmarshal some json data I get from a web service. I have simplified the problem which is shown in the code below. My question is can I make version (c) in the code work..

I know it works for single number values as shown for "timestamp" by adding the option ",string" to the json annotation. But I can't figure out how or if this works for arrays of string encoded numbers too. (See "conversions" in the example json listed in the code)

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)
    }  
}

If i compile and run the code I get this output:

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

You can run the code here: http://play.golang.org/p/4TC0IgCI8H

Is there a way to achieve unmarshaling into struct version (c)? Thanks for your help!

3个回答

The easiest way I know to do this is to define a new type and then define UnmarshalJSON for it:

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, see version (d). This is not the most perfect way to do that and the algorithm can be improved to use less resources, but you get the idea.

dousi0144
dousi0144 我最喜欢这个答案,因为它可以直接使用我定义的结构进行存储,而不必定义另一个结构来首先临时存储未编组的数据。 做得好! 谢谢
大约 6 年之前 回复



您不能这样做,因为您将它们作为字符串传递,所以最好的选择实际上是使用 json.Number </ code >并编写如下函数:</ p>

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

展开原文

原文

You can't do that since you pass them as strings, your best bet really is using json.Number and write a function like:

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



如果将“放在数字周围,它们将被视为字符串。实际上,在前两个结构中,您没有任何问题。 </ p>

如果要将它们转换为数字类型,请使用正确的方法来做到这一点:解析浮点数 </ p>

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

展开原文

原文

If you put " around the numbers they are considered like string. In fact, in the first two structure you haven't any problem.

If you want to convert them into numeric type, use the correct method to do that: parse float

Here you can see how you can use ParseFloat: http://play.golang.org/p/XDuiF0FCQq

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐