You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
When decoding a non-string literal into an encoding.TextUnmarshaler (such as net.IP), json.Unmarshal returns errPhase ("JSON decoder out of sync - data changing underfoot?").
Reading the code, it seems like it's supposed to return a type error when this happens
(source). But the errPhase ends up taking precedence and obscuring this message.
I'm not sure why UnmarshalText should only work for string literals, though.
package main
import (
"encoding/json"
"fmt"
"net"
"strconv"
)
type X int
func (x *X) UnmarshalText(b []byte) error {
n, err := strconv.ParseInt(string(b), 10, 64)
if err != nil {
return err
}
*x = X(n)
return nil
}
func main() {
var x X
err := x.UnmarshalText([]byte("123"))
fmt.Println(x, err) // 123 <nil>
// Works if the string is quoted
err = json.Unmarshal([]byte(`"234"`), &x)
fmt.Println(x, err) // 234 <nil>
// Otherwise it gives an errPhase
err = json.Unmarshal([]byte("123"), &x)
fmt.Println(err) // JSON decoder out of sync - data changing underfoot?
err = json.Unmarshal([]byte("true"), &x)
fmt.Println(err) // JSON decoder out of sync - data changing underfoot?
err = json.Unmarshal([]byte("null"), &x)
fmt.Println(err) // JSON decoder out of sync - data changing underfoot?
// Happens with real types like net.IP
var ip net.IP
err = json.Unmarshal([]byte("8080"), &ip)
fmt.Println(err) // JSON decoder out of sync - data changing underfoot?
}
The text was updated successfully, but these errors were encountered:
@cespare sure, just pointing that out as a possible hint for debugging.
cespare
changed the title
encoding/json: Unmarshal gives errPhase on non-string literal when underlying TextUnmarshaler returns an error
encoding/json: Decoding gives errPhase when unmarshaling a non-string literal into a TextUnmarshaler
Jan 21, 2015
Can we infer from your fix that unmarshaling a non-string value, even null, into a TextUnmarshaler is always an error? That is, null can't be unmarshaled into a *net.IP, even though both *net.IP and net.IP can be nil?
The error now reads cannot unmarshal string into Go value of type [...] when trying to unmarshal null. Should null really be considered a string, or should an issue be filed for this?
updated
When decoding a non-string literal into an
encoding.TextUnmarshaler
(such asnet.IP
),json.Unmarshal
returnserrPhase
("JSON decoder out of sync - data changing underfoot?").Reading the code, it seems like it's supposed to return a type error when this happens
(source). But the
errPhase
ends up taking precedence and obscuring this message.I'm not sure why
UnmarshalText
should only work for string literals, though.Example play here.
Code:
The text was updated successfully, but these errors were encountered: