Merge pull request #411 from neal/bugfix/unmarshal-unexpected-null

Fix unmarshal null values for non-pointer fields
This commit is contained in:
Vasily Romanov
2025-01-11 22:28:08 +03:00
committed by GitHub
2 changed files with 41 additions and 10 deletions
+32 -8
View File
@@ -63,22 +63,34 @@ func (g *Generator) genTypeDecoder(t reflect.Type, out string, tags fieldTags, i
unmarshalerIface := reflect.TypeOf((*easyjson.Unmarshaler)(nil)).Elem()
if reflect.PtrTo(t).Implements(unmarshalerIface) {
fmt.Fprintln(g.out, ws+"("+out+").UnmarshalEasyJSON(in)")
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" ("+out+").UnmarshalEasyJSON(in)")
fmt.Fprintln(g.out, ws+"}")
return nil
}
unmarshalerIface = reflect.TypeOf((*json.Unmarshaler)(nil)).Elem()
if reflect.PtrTo(t).Implements(unmarshalerIface) {
fmt.Fprintln(g.out, ws+"if data := in.Raw(); in.Ok() {")
fmt.Fprintln(g.out, ws+" in.AddError( ("+out+").UnmarshalJSON(data) )")
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" if data := in.Raw(); in.Ok() {")
fmt.Fprintln(g.out, ws+" in.AddError( ("+out+").UnmarshalJSON(data) )")
fmt.Fprintln(g.out, ws+" }")
fmt.Fprintln(g.out, ws+"}")
return nil
}
unmarshalerIface = reflect.TypeOf((*encoding.TextUnmarshaler)(nil)).Elem()
if reflect.PtrTo(t).Implements(unmarshalerIface) {
fmt.Fprintln(g.out, ws+"if data := in.UnsafeBytes(); in.Ok() {")
fmt.Fprintln(g.out, ws+" in.AddError( ("+out+").UnmarshalText(data) )")
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" if data := in.UnsafeBytes(); in.Ok() {")
fmt.Fprintln(g.out, ws+" in.AddError( ("+out+").UnmarshalText(data) )")
fmt.Fprintln(g.out, ws+" }")
fmt.Fprintln(g.out, ws+"}")
return nil
}
@@ -110,13 +122,21 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field
ws := strings.Repeat(" ", indent)
// Check whether type is primitive, needs to be done after interface check.
if dec := customDecoders[t.String()]; dec != "" {
fmt.Fprintln(g.out, ws+out+" = "+dec)
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" "+out+" = "+dec)
fmt.Fprintln(g.out, ws+"}")
return nil
} else if dec := primitiveStringDecoders[t.Kind()]; dec != "" && tags.asString {
if tags.intern && t.Kind() == reflect.String {
dec = "in.StringIntern()"
}
fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" "+out+" = "+g.getType(t)+"("+dec+")")
fmt.Fprintln(g.out, ws+"}")
return nil
} else if dec := primitiveDecoders[t.Kind()]; dec != "" {
if tags.intern && t.Kind() == reflect.String {
@@ -125,7 +145,11 @@ func (g *Generator) genTypeDecoderNoCheck(t reflect.Type, out string, tags field
if tags.noCopy && t.Kind() == reflect.String {
dec = "in.UnsafeString()"
}
fmt.Fprintln(g.out, ws+out+" = "+g.getType(t)+"("+dec+")")
fmt.Fprintln(g.out, ws+"if in.IsNull() {")
fmt.Fprintln(g.out, ws+" in.Skip()")
fmt.Fprintln(g.out, ws+"} else {")
fmt.Fprintln(g.out, ws+" "+out+" = "+g.getType(t)+"("+dec+")")
fmt.Fprintln(g.out, ws+"}")
return nil
}
+9 -2
View File
@@ -330,14 +330,21 @@ func TestNil(t *testing.T) {
}
func TestUnmarshalNull(t *testing.T) {
p := primitiveTypesValue
p := PrimitiveTypes{
String: str,
Ptr: &str,
}
data := `{"Ptr":null}`
data := `{"String":null,"Ptr":null}`
if err := easyjson.Unmarshal([]byte(data), &p); err != nil {
t.Errorf("easyjson.Unmarshal() error: %v", err)
}
if p.String != str {
t.Errorf("Wanted %q, got %q", str, p.String)
}
if p.Ptr != nil {
t.Errorf("Wanted nil, got %q", *p.Ptr)
}