Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
G
go
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
Analytics
Analytics
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Commits
Issue Boards
Open sidebar
Kirill Smelkov
go
Commits
fc5889d4
Commit
fc5889d4
authored
Sep 19, 2011
by
Russ Cox
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
json: skip nil in UnmarshalJSON and (for symmetry) MarshalJSON
R=dsymonds, r CC=golang-dev
https://golang.org/cl/5050049
parent
003bfa0e
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
42 additions
and
13 deletions
+42
-13
src/pkg/json/decode.go
src/pkg/json/decode.go
+11
-10
src/pkg/json/encode.go
src/pkg/json/encode.go
+6
-3
src/pkg/json/stream_test.go
src/pkg/json/stream_test.go
+25
-0
No files found.
src/pkg/json/decode.go
View file @
fc5889d4
...
@@ -22,16 +22,11 @@ import (
...
@@ -22,16 +22,11 @@ import (
// Unmarshal parses the JSON-encoded data and stores the result
// Unmarshal parses the JSON-encoded data and stores the result
// in the value pointed to by v.
// in the value pointed to by v.
//
//
// Unmarshal traverses the value v recursively.
// Unmarshal uses the inverse of the encodings that
// If an encountered value implements the Unmarshaler interface,
// Unmarshal calls its UnmarshalJSON method with a well-formed
// JSON encoding.
//
// Otherwise, Unmarshal uses the inverse of the encodings that
// Marshal uses, allocating maps, slices, and pointers as necessary,
// Marshal uses, allocating maps, slices, and pointers as necessary,
// with the following additional rules:
// with the following additional rules:
//
//
// To unmarshal
a JSON value
into a nil interface value, the
// To unmarshal
JSON
into a nil interface value, the
// type stored in the interface value is one of:
// type stored in the interface value is one of:
//
//
// bool, for JSON booleans
// bool, for JSON booleans
...
@@ -41,6 +36,12 @@ import (
...
@@ -41,6 +36,12 @@ import (
// map[string]interface{}, for JSON objects
// map[string]interface{}, for JSON objects
// nil for JSON null
// nil for JSON null
//
//
// To unmarshal JSON into a pointer, Unmarshal first handles the case of
// the JSON being the JSON literal null. In that case, Unmarshal sets
// the pointer to nil. Otherwise, Unmarshal unmarshals the JSON into
// the value pointed at by the pointer. If the pointer is nil, Unmarshal
// allocates a new value for it to point to.
//
// If a JSON value is not appropriate for a given target type,
// If a JSON value is not appropriate for a given target type,
// or if a JSON number overflows the target type, Unmarshal
// or if a JSON number overflows the target type, Unmarshal
// skips that field and completes the unmarshalling as best it can.
// skips that field and completes the unmarshalling as best it can.
...
@@ -250,8 +251,8 @@ func (d *decodeState) value(v reflect.Value) {
...
@@ -250,8 +251,8 @@ func (d *decodeState) value(v reflect.Value) {
// indirect walks down v allocating pointers as needed,
// indirect walks down v allocating pointers as needed,
// until it gets to a non-pointer.
// until it gets to a non-pointer.
// if it encounters an Unmarshaler, indirect stops and returns that.
// if it encounters an Unmarshaler, indirect stops and returns that.
// if
wantptr is true, indirect stops at the last pointer
.
// if
decodingNull is true, indirect stops at the last pointer so it can be set to nil
.
func
(
d
*
decodeState
)
indirect
(
v
reflect
.
Value
,
wantptr
bool
)
(
Unmarshaler
,
reflect
.
Value
)
{
func
(
d
*
decodeState
)
indirect
(
v
reflect
.
Value
,
decodingNull
bool
)
(
Unmarshaler
,
reflect
.
Value
)
{
// If v is a named type and is addressable,
// If v is a named type and is addressable,
// start with its address, so that if the type has pointer methods,
// start with its address, so that if the type has pointer methods,
// we find them.
// we find them.
...
@@ -277,7 +278,7 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
...
@@ -277,7 +278,7 @@ func (d *decodeState) indirect(v reflect.Value, wantptr bool) (Unmarshaler, refl
break
break
}
}
if
pv
.
Elem
()
.
Kind
()
!=
reflect
.
Ptr
&&
wantptr
&&
pv
.
CanSet
()
&&
!
isUnmarshaler
{
if
pv
.
Elem
()
.
Kind
()
!=
reflect
.
Ptr
&&
decodingNull
&&
pv
.
CanSet
()
{
return
nil
,
pv
return
nil
,
pv
}
}
if
pv
.
IsNil
()
{
if
pv
.
IsNil
()
{
...
...
src/pkg/json/encode.go
View file @
fc5889d4
...
@@ -24,8 +24,11 @@ import (
...
@@ -24,8 +24,11 @@ import (
// Marshal returns the JSON encoding of v.
// Marshal returns the JSON encoding of v.
//
//
// Marshal traverses the value v recursively.
// Marshal traverses the value v recursively.
// If an encountered value implements the Marshaler interface,
// If an encountered value implements the Marshaler interface
// Marshal calls its MarshalJSON method to produce JSON.
// and is not a nil pointer, Marshal calls its MarshalJSON method
// to produce JSON. The nil pointer exception is not strictly necessary
// but mimics a similar, necessary exception in the behavior of
// UnmarshalJSON.
//
//
// Otherwise, Marshal uses the following type-dependent default encodings:
// Otherwise, Marshal uses the following type-dependent default encodings:
//
//
...
@@ -245,7 +248,7 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
...
@@ -245,7 +248,7 @@ func (e *encodeState) reflectValueQuoted(v reflect.Value, quoted bool) {
return
return
}
}
if
j
,
ok
:=
v
.
Interface
()
.
(
Marshaler
);
ok
{
if
j
,
ok
:=
v
.
Interface
()
.
(
Marshaler
);
ok
&&
(
v
.
Kind
()
!=
reflect
.
Ptr
||
!
v
.
IsNil
())
{
b
,
err
:=
j
.
MarshalJSON
()
b
,
err
:=
j
.
MarshalJSON
()
if
err
==
nil
{
if
err
==
nil
{
// copy JSON into buffer, checking validity.
// copy JSON into buffer, checking validity.
...
...
src/pkg/json/stream_test.go
View file @
fc5889d4
...
@@ -120,3 +120,28 @@ func TestRawMessage(t *testing.T) {
...
@@ -120,3 +120,28 @@ func TestRawMessage(t *testing.T) {
t
.
Fatalf
(
"Marshal: have %#q want %#q"
,
b
,
msg
)
t
.
Fatalf
(
"Marshal: have %#q want %#q"
,
b
,
msg
)
}
}
}
}
func
TestNullRawMessage
(
t
*
testing
.
T
)
{
// TODO(rsc): Should not need the * in *RawMessage
var
data
struct
{
X
float64
Id
*
RawMessage
Y
float32
}
data
.
Id
=
new
(
RawMessage
)
const
msg
=
`{"X":0.1,"Id":null,"Y":0.2}`
err
:=
Unmarshal
([]
byte
(
msg
),
&
data
)
if
err
!=
nil
{
t
.
Fatalf
(
"Unmarshal: %v"
,
err
)
}
if
data
.
Id
!=
nil
{
t
.
Fatalf
(
"Raw mismatch: have non-nil, want nil"
)
}
b
,
err
:=
Marshal
(
&
data
)
if
err
!=
nil
{
t
.
Fatalf
(
"Marshal: %v"
,
err
)
}
if
string
(
b
)
!=
msg
{
t
.
Fatalf
(
"Marshal: have %#q want %#q"
,
b
,
msg
)
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment