简体   繁体   English

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

[英]How to unmarshal an array of string encoded floats to an array of floats?

I'm trying to unmarshal some json data I get from a web service. 我正在尝试解组从Web服务获得的一些json数据。 I have simplified the problem which is shown in the code below. 我已经简化了下面代码中显示的问题。 My question is can I make version (c) in the code work.. 我的问题是我可以在代码工作中制作版本(c)。

I know it works for single number values as shown for "timestamp" by adding the option ",string" to the json annotation. 我知道它适用于单个数字值,如“timestamp”所示,方法是在json注释中添加选项“,string”。 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) (参见代码中列出的示例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)
    }  
}

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 您可以在此处运行代码: http//play.golang.org/p/4TC0IgCI8H

Is there a way to achieve unmarshaling into struct version (c)? 有没有办法实现对struct version(c)的解组? Thanks for your help! 谢谢你的帮助!

The easiest way I know to do this is to define a new type and then define UnmarshalJSON for it: 我知道这样做的最简单方法是定义一个新类型,然后为它定义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 , see version (d). 游乐场 ,见版本(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. 这不是最完美的方法,可以改进算法以减少资源使用,但你明白了。

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 如果要将它们转换为数字类型,请使用正确的方法执行此操作: 解析float

Here you can see how you can use ParseFloat: http://play.golang.org/p/XDuiF0FCQq 在这里你可以看到如何使用ParseFloat: http ://play.golang.org/p/XDuiF0FCQq

You can't do that since you pass them as strings, your best bet really is using json.Number and write a function like: 你不能这样做,因为你把它们作为字符串传递,你最好的选择是使用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])

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM