The external API that my application is using, sometimes returns no values for one of the float64 fields. When that happens, I cannot unmarshal the rest of the document.
Here is the sample code in Go playground:
http://play.golang.org/p/Twv8b6KCtw
package main
import (
"encoding/xml"
"fmt"
)
func main() {
type Result struct {
XMLName xml.Name `xml:"Person"`
Grade float64 `xml:"grade"`
Name string `xml:"name"`
}
data := `
<Person>
<grade/>
<name>Jack</name>
</Person>
`
var v Result
err := xml.Unmarshal([]byte(data), &v)
if err != nil {
fmt.Printf("error: %v", err)
return
}
fmt.Printf("name: %s
", v.Name)
}
If I change float64 in line 12 to string, it will work. Any idea how I can get a workaround for this? Should I just define every field as string and do the conversion manually?
I believe you have discovered a bug, you should report it on the issue tracker, I submitted a bug report issue 8333.
Now for the current problem, you have 2 options:
string
type they do your own conversation to float on demand.<grade/>
tag completely and use xml:"grade,omitempty"
in your struct.To add to OneOfOne's solutions, you can also define your own UnmarshalXML
method.
Example (On play):
type Grade float64
func (g *Grade) UnmarshalXML(d *xml.Decoder, s xml.StartElement) error {
for tok, err := d.Token(); err != io.EOF; tok, err = d.Token() {
if chrdata, ok := tok.(xml.CharData); ok {
f, err := strconv.ParseFloat(string(chrdata), 64)
if err != nil {
return err
}
*(*float64)(g) = f
}
}
return nil
}
type Result struct {
XMLName xml.Name `xml:"Person"`
Grade Grade `xml:"grade"`
Name string `xml:"name"`
}
This parses the <grade>
tag by searching for CharData
tokens in between and parsing them as float, leaving the grade at 0.0
when there is no value to be parsed.