• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1// Go support for Protocol Buffers - Google's data interchange format
2//
3// Copyright 2015 The Go Authors.  All rights reserved.
4// https://github.com/golang/protobuf
5//
6// Redistribution and use in source and binary forms, with or without
7// modification, are permitted provided that the following conditions are
8// met:
9//
10//     * Redistributions of source code must retain the above copyright
11// notice, this list of conditions and the following disclaimer.
12//     * Redistributions in binary form must reproduce the above
13// copyright notice, this list of conditions and the following disclaimer
14// in the documentation and/or other materials provided with the
15// distribution.
16//     * Neither the name of Google Inc. nor the names of its
17// contributors may be used to endorse or promote products derived from
18// this software without specific prior written permission.
19//
20// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
21// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
22// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
23// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
24// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
25// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
26// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
27// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
28// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
29// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
30// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
31
32package jsonpb
33
34import (
35	"bytes"
36	"encoding/json"
37	"io"
38	"math"
39	"reflect"
40	"strings"
41	"testing"
42
43	"github.com/golang/protobuf/proto"
44
45	pb "github.com/golang/protobuf/jsonpb/jsonpb_test_proto"
46	proto3pb "github.com/golang/protobuf/proto/proto3_proto"
47	"github.com/golang/protobuf/ptypes"
48	anypb "github.com/golang/protobuf/ptypes/any"
49	durpb "github.com/golang/protobuf/ptypes/duration"
50	stpb "github.com/golang/protobuf/ptypes/struct"
51	tspb "github.com/golang/protobuf/ptypes/timestamp"
52	wpb "github.com/golang/protobuf/ptypes/wrappers"
53)
54
55var (
56	marshaler = Marshaler{}
57
58	marshalerAllOptions = Marshaler{
59		Indent: "  ",
60	}
61
62	simpleObject = &pb.Simple{
63		OInt32:     proto.Int32(-32),
64		OInt32Str:  proto.Int32(-32),
65		OInt64:     proto.Int64(-6400000000),
66		OInt64Str:  proto.Int64(-6400000000),
67		OUint32:    proto.Uint32(32),
68		OUint32Str: proto.Uint32(32),
69		OUint64:    proto.Uint64(6400000000),
70		OUint64Str: proto.Uint64(6400000000),
71		OSint32:    proto.Int32(-13),
72		OSint32Str: proto.Int32(-13),
73		OSint64:    proto.Int64(-2600000000),
74		OSint64Str: proto.Int64(-2600000000),
75		OFloat:     proto.Float32(3.14),
76		OFloatStr:  proto.Float32(3.14),
77		ODouble:    proto.Float64(6.02214179e23),
78		ODoubleStr: proto.Float64(6.02214179e23),
79		OBool:      proto.Bool(true),
80		OString:    proto.String("hello \"there\""),
81		OBytes:     []byte("beep boop"),
82	}
83
84	simpleObjectInputJSON = `{` +
85		`"oBool":true,` +
86		`"oInt32":-32,` +
87		`"oInt32Str":"-32",` +
88		`"oInt64":-6400000000,` +
89		`"oInt64Str":"-6400000000",` +
90		`"oUint32":32,` +
91		`"oUint32Str":"32",` +
92		`"oUint64":6400000000,` +
93		`"oUint64Str":"6400000000",` +
94		`"oSint32":-13,` +
95		`"oSint32Str":"-13",` +
96		`"oSint64":-2600000000,` +
97		`"oSint64Str":"-2600000000",` +
98		`"oFloat":3.14,` +
99		`"oFloatStr":"3.14",` +
100		`"oDouble":6.02214179e+23,` +
101		`"oDoubleStr":"6.02214179e+23",` +
102		`"oString":"hello \"there\"",` +
103		`"oBytes":"YmVlcCBib29w"` +
104		`}`
105
106	simpleObjectOutputJSON = `{` +
107		`"oBool":true,` +
108		`"oInt32":-32,` +
109		`"oInt32Str":-32,` +
110		`"oInt64":"-6400000000",` +
111		`"oInt64Str":"-6400000000",` +
112		`"oUint32":32,` +
113		`"oUint32Str":32,` +
114		`"oUint64":"6400000000",` +
115		`"oUint64Str":"6400000000",` +
116		`"oSint32":-13,` +
117		`"oSint32Str":-13,` +
118		`"oSint64":"-2600000000",` +
119		`"oSint64Str":"-2600000000",` +
120		`"oFloat":3.14,` +
121		`"oFloatStr":3.14,` +
122		`"oDouble":6.02214179e+23,` +
123		`"oDoubleStr":6.02214179e+23,` +
124		`"oString":"hello \"there\"",` +
125		`"oBytes":"YmVlcCBib29w"` +
126		`}`
127
128	simpleObjectInputPrettyJSON = `{
129  "oBool": true,
130  "oInt32": -32,
131  "oInt32Str": "-32",
132  "oInt64": -6400000000,
133  "oInt64Str": "-6400000000",
134  "oUint32": 32,
135  "oUint32Str": "32",
136  "oUint64": 6400000000,
137  "oUint64Str": "6400000000",
138  "oSint32": -13,
139  "oSint32Str": "-13",
140  "oSint64": -2600000000,
141  "oSint64Str": "-2600000000",
142  "oFloat": 3.14,
143  "oFloatStr": "3.14",
144  "oDouble": 6.02214179e+23,
145  "oDoubleStr": "6.02214179e+23",
146  "oString": "hello \"there\"",
147  "oBytes": "YmVlcCBib29w"
148}`
149
150	simpleObjectOutputPrettyJSON = `{
151  "oBool": true,
152  "oInt32": -32,
153  "oInt32Str": -32,
154  "oInt64": "-6400000000",
155  "oInt64Str": "-6400000000",
156  "oUint32": 32,
157  "oUint32Str": 32,
158  "oUint64": "6400000000",
159  "oUint64Str": "6400000000",
160  "oSint32": -13,
161  "oSint32Str": -13,
162  "oSint64": "-2600000000",
163  "oSint64Str": "-2600000000",
164  "oFloat": 3.14,
165  "oFloatStr": 3.14,
166  "oDouble": 6.02214179e+23,
167  "oDoubleStr": 6.02214179e+23,
168  "oString": "hello \"there\"",
169  "oBytes": "YmVlcCBib29w"
170}`
171
172	repeatsObject = &pb.Repeats{
173		RBool:   []bool{true, false, true},
174		RInt32:  []int32{-3, -4, -5},
175		RInt64:  []int64{-123456789, -987654321},
176		RUint32: []uint32{1, 2, 3},
177		RUint64: []uint64{6789012345, 3456789012},
178		RSint32: []int32{-1, -2, -3},
179		RSint64: []int64{-6789012345, -3456789012},
180		RFloat:  []float32{3.14, 6.28},
181		RDouble: []float64{299792458 * 1e20, 6.62606957e-34},
182		RString: []string{"happy", "days"},
183		RBytes:  [][]byte{[]byte("skittles"), []byte("m&m's")},
184	}
185
186	repeatsObjectJSON = `{` +
187		`"rBool":[true,false,true],` +
188		`"rInt32":[-3,-4,-5],` +
189		`"rInt64":["-123456789","-987654321"],` +
190		`"rUint32":[1,2,3],` +
191		`"rUint64":["6789012345","3456789012"],` +
192		`"rSint32":[-1,-2,-3],` +
193		`"rSint64":["-6789012345","-3456789012"],` +
194		`"rFloat":[3.14,6.28],` +
195		`"rDouble":[2.99792458e+28,6.62606957e-34],` +
196		`"rString":["happy","days"],` +
197		`"rBytes":["c2tpdHRsZXM=","bSZtJ3M="]` +
198		`}`
199
200	repeatsObjectPrettyJSON = `{
201  "rBool": [
202    true,
203    false,
204    true
205  ],
206  "rInt32": [
207    -3,
208    -4,
209    -5
210  ],
211  "rInt64": [
212    "-123456789",
213    "-987654321"
214  ],
215  "rUint32": [
216    1,
217    2,
218    3
219  ],
220  "rUint64": [
221    "6789012345",
222    "3456789012"
223  ],
224  "rSint32": [
225    -1,
226    -2,
227    -3
228  ],
229  "rSint64": [
230    "-6789012345",
231    "-3456789012"
232  ],
233  "rFloat": [
234    3.14,
235    6.28
236  ],
237  "rDouble": [
238    2.99792458e+28,
239    6.62606957e-34
240  ],
241  "rString": [
242    "happy",
243    "days"
244  ],
245  "rBytes": [
246    "c2tpdHRsZXM=",
247    "bSZtJ3M="
248  ]
249}`
250
251	innerSimple   = &pb.Simple{OInt32: proto.Int32(-32)}
252	innerSimple2  = &pb.Simple{OInt64: proto.Int64(25)}
253	innerRepeats  = &pb.Repeats{RString: []string{"roses", "red"}}
254	innerRepeats2 = &pb.Repeats{RString: []string{"violets", "blue"}}
255	complexObject = &pb.Widget{
256		Color:    pb.Widget_GREEN.Enum(),
257		RColor:   []pb.Widget_Color{pb.Widget_RED, pb.Widget_GREEN, pb.Widget_BLUE},
258		Simple:   innerSimple,
259		RSimple:  []*pb.Simple{innerSimple, innerSimple2},
260		Repeats:  innerRepeats,
261		RRepeats: []*pb.Repeats{innerRepeats, innerRepeats2},
262	}
263
264	complexObjectJSON = `{"color":"GREEN",` +
265		`"rColor":["RED","GREEN","BLUE"],` +
266		`"simple":{"oInt32":-32},` +
267		`"rSimple":[{"oInt32":-32},{"oInt64":"25"}],` +
268		`"repeats":{"rString":["roses","red"]},` +
269		`"rRepeats":[{"rString":["roses","red"]},{"rString":["violets","blue"]}]` +
270		`}`
271
272	complexObjectPrettyJSON = `{
273  "color": "GREEN",
274  "rColor": [
275    "RED",
276    "GREEN",
277    "BLUE"
278  ],
279  "simple": {
280    "oInt32": -32
281  },
282  "rSimple": [
283    {
284      "oInt32": -32
285    },
286    {
287      "oInt64": "25"
288    }
289  ],
290  "repeats": {
291    "rString": [
292      "roses",
293      "red"
294    ]
295  },
296  "rRepeats": [
297    {
298      "rString": [
299        "roses",
300        "red"
301      ]
302    },
303    {
304      "rString": [
305        "violets",
306        "blue"
307      ]
308    }
309  ]
310}`
311
312	colorPrettyJSON = `{
313 "color": 2
314}`
315
316	colorListPrettyJSON = `{
317  "color": 1000,
318  "rColor": [
319    "RED"
320  ]
321}`
322
323	nummyPrettyJSON = `{
324  "nummy": {
325    "1": 2,
326    "3": 4
327  }
328}`
329
330	objjyPrettyJSON = `{
331  "objjy": {
332    "1": {
333      "dub": 1
334    }
335  }
336}`
337	realNumber     = &pb.Real{Value: proto.Float64(3.14159265359)}
338	realNumberName = "Pi"
339	complexNumber  = &pb.Complex{Imaginary: proto.Float64(0.5772156649)}
340	realNumberJSON = `{` +
341		`"value":3.14159265359,` +
342		`"[jsonpb.Complex.real_extension]":{"imaginary":0.5772156649},` +
343		`"[jsonpb.name]":"Pi"` +
344		`}`
345
346	anySimple = &pb.KnownTypes{
347		An: &anypb.Any{
348			TypeUrl: "something.example.com/jsonpb.Simple",
349			Value: []byte{
350				// &pb.Simple{OBool:true}
351				1 << 3, 1,
352			},
353		},
354	}
355	anySimpleJSON       = `{"an":{"@type":"something.example.com/jsonpb.Simple","oBool":true}}`
356	anySimplePrettyJSON = `{
357  "an": {
358    "@type": "something.example.com/jsonpb.Simple",
359    "oBool": true
360  }
361}`
362
363	anyWellKnown = &pb.KnownTypes{
364		An: &anypb.Any{
365			TypeUrl: "type.googleapis.com/google.protobuf.Duration",
366			Value: []byte{
367				// &durpb.Duration{Seconds: 1, Nanos: 212000000 }
368				1 << 3, 1, // seconds
369				2 << 3, 0x80, 0xba, 0x8b, 0x65, // nanos
370			},
371		},
372	}
373	anyWellKnownJSON       = `{"an":{"@type":"type.googleapis.com/google.protobuf.Duration","value":"1.212s"}}`
374	anyWellKnownPrettyJSON = `{
375  "an": {
376    "@type": "type.googleapis.com/google.protobuf.Duration",
377    "value": "1.212s"
378  }
379}`
380
381	nonFinites = &pb.NonFinites{
382		FNan:  proto.Float32(float32(math.NaN())),
383		FPinf: proto.Float32(float32(math.Inf(1))),
384		FNinf: proto.Float32(float32(math.Inf(-1))),
385		DNan:  proto.Float64(float64(math.NaN())),
386		DPinf: proto.Float64(float64(math.Inf(1))),
387		DNinf: proto.Float64(float64(math.Inf(-1))),
388	}
389	nonFinitesJSON = `{` +
390		`"fNan":"NaN",` +
391		`"fPinf":"Infinity",` +
392		`"fNinf":"-Infinity",` +
393		`"dNan":"NaN",` +
394		`"dPinf":"Infinity",` +
395		`"dNinf":"-Infinity"` +
396		`}`
397)
398
399func init() {
400	if err := proto.SetExtension(realNumber, pb.E_Name, &realNumberName); err != nil {
401		panic(err)
402	}
403	if err := proto.SetExtension(realNumber, pb.E_Complex_RealExtension, complexNumber); err != nil {
404		panic(err)
405	}
406}
407
408var marshalingTests = []struct {
409	desc      string
410	marshaler Marshaler
411	pb        proto.Message
412	json      string
413}{
414	{"simple flat object", marshaler, simpleObject, simpleObjectOutputJSON},
415	{"simple pretty object", marshalerAllOptions, simpleObject, simpleObjectOutputPrettyJSON},
416	{"non-finite floats fields object", marshaler, nonFinites, nonFinitesJSON},
417	{"repeated fields flat object", marshaler, repeatsObject, repeatsObjectJSON},
418	{"repeated fields pretty object", marshalerAllOptions, repeatsObject, repeatsObjectPrettyJSON},
419	{"nested message/enum flat object", marshaler, complexObject, complexObjectJSON},
420	{"nested message/enum pretty object", marshalerAllOptions, complexObject, complexObjectPrettyJSON},
421	{"enum-string flat object", Marshaler{},
422		&pb.Widget{Color: pb.Widget_BLUE.Enum()}, `{"color":"BLUE"}`},
423	{"enum-value pretty object", Marshaler{EnumsAsInts: true, Indent: " "},
424		&pb.Widget{Color: pb.Widget_BLUE.Enum()}, colorPrettyJSON},
425	{"unknown enum value object", marshalerAllOptions,
426		&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}, colorListPrettyJSON},
427	{"repeated proto3 enum", Marshaler{},
428		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
429			proto3pb.Message_PUNS,
430			proto3pb.Message_SLAPSTICK,
431		}},
432		`{"rFunny":["PUNS","SLAPSTICK"]}`},
433	{"repeated proto3 enum as int", Marshaler{EnumsAsInts: true},
434		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
435			proto3pb.Message_PUNS,
436			proto3pb.Message_SLAPSTICK,
437		}},
438		`{"rFunny":[1,2]}`},
439	{"empty value", marshaler, &pb.Simple3{}, `{}`},
440	{"empty value emitted", Marshaler{EmitDefaults: true}, &pb.Simple3{}, `{"dub":0}`},
441	{"empty repeated emitted", Marshaler{EmitDefaults: true}, &pb.SimpleSlice3{}, `{"slices":[]}`},
442	{"empty map emitted", Marshaler{EmitDefaults: true}, &pb.SimpleMap3{}, `{"stringy":{}}`},
443	{"nested struct null", Marshaler{EmitDefaults: true}, &pb.SimpleNull3{}, `{"simple":null}`},
444	{"map<int64, int32>", marshaler, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, `{"nummy":{"1":2,"3":4}}`},
445	{"map<int64, int32>", marshalerAllOptions, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}, nummyPrettyJSON},
446	{"map<string, string>", marshaler,
447		&pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}},
448		`{"strry":{"\"one\"":"two","three":"four"}}`},
449	{"map<int32, Object>", marshaler,
450		&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, `{"objjy":{"1":{"dub":1}}}`},
451	{"map<int32, Object>", marshalerAllOptions,
452		&pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}, objjyPrettyJSON},
453	{"map<int64, string>", marshaler, &pb.Mappy{Buggy: map[int64]string{1234: "yup"}},
454		`{"buggy":{"1234":"yup"}}`},
455	{"map<bool, bool>", marshaler, &pb.Mappy{Booly: map[bool]bool{false: true}}, `{"booly":{"false":true}}`},
456	{"map<string, enum>", marshaler, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":"ROMAN"}}`},
457	{"map<string, enum as int>", Marshaler{EnumsAsInts: true}, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}, `{"enumy":{"XIV":2}}`},
458	{"map<int32, bool>", marshaler, &pb.Mappy{S32Booly: map[int32]bool{1: true, 3: false, 10: true, 12: false}}, `{"s32booly":{"1":true,"3":false,"10":true,"12":false}}`},
459	{"map<int64, bool>", marshaler, &pb.Mappy{S64Booly: map[int64]bool{1: true, 3: false, 10: true, 12: false}}, `{"s64booly":{"1":true,"3":false,"10":true,"12":false}}`},
460	{"map<uint32, bool>", marshaler, &pb.Mappy{U32Booly: map[uint32]bool{1: true, 3: false, 10: true, 12: false}}, `{"u32booly":{"1":true,"3":false,"10":true,"12":false}}`},
461	{"map<uint64, bool>", marshaler, &pb.Mappy{U64Booly: map[uint64]bool{1: true, 3: false, 10: true, 12: false}}, `{"u64booly":{"1":true,"3":false,"10":true,"12":false}}`},
462	{"proto2 map<int64, string>", marshaler, &pb.Maps{MInt64Str: map[int64]string{213: "cat"}},
463		`{"mInt64Str":{"213":"cat"}}`},
464	{"proto2 map<bool, Object>", marshaler,
465		&pb.Maps{MBoolSimple: map[bool]*pb.Simple{true: {OInt32: proto.Int32(1)}}},
466		`{"mBoolSimple":{"true":{"oInt32":1}}}`},
467	{"oneof, not set", marshaler, &pb.MsgWithOneof{}, `{}`},
468	{"oneof, set", marshaler, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Title{"Grand Poobah"}}, `{"title":"Grand Poobah"}`},
469	{"force orig_name", Marshaler{OrigName: true}, &pb.Simple{OInt32: proto.Int32(4)},
470		`{"o_int32":4}`},
471	{"proto2 extension", marshaler, realNumber, realNumberJSON},
472	{"Any with message", marshaler, anySimple, anySimpleJSON},
473	{"Any with message and indent", marshalerAllOptions, anySimple, anySimplePrettyJSON},
474	{"Any with WKT", marshaler, anyWellKnown, anyWellKnownJSON},
475	{"Any with WKT and indent", marshalerAllOptions, anyWellKnown, anyWellKnownPrettyJSON},
476	{"Duration empty", marshaler, &durpb.Duration{}, `"0s"`},
477	{"Duration with secs", marshaler, &durpb.Duration{Seconds: 3}, `"3s"`},
478	{"Duration with -secs", marshaler, &durpb.Duration{Seconds: -3}, `"-3s"`},
479	{"Duration with nanos", marshaler, &durpb.Duration{Nanos: 1e6}, `"0.001s"`},
480	{"Duration with -nanos", marshaler, &durpb.Duration{Nanos: -1e6}, `"-0.001s"`},
481	{"Duration with large secs", marshaler, &durpb.Duration{Seconds: 1e10, Nanos: 1}, `"10000000000.000000001s"`},
482	{"Duration with 6-digit nanos", marshaler, &durpb.Duration{Nanos: 1e4}, `"0.000010s"`},
483	{"Duration with 3-digit nanos", marshaler, &durpb.Duration{Nanos: 1e6}, `"0.001s"`},
484	{"Duration with -secs -nanos", marshaler, &durpb.Duration{Seconds: -123, Nanos: -450}, `"-123.000000450s"`},
485	{"Duration max value", marshaler, &durpb.Duration{Seconds: 315576000000, Nanos: 999999999}, `"315576000000.999999999s"`},
486	{"Duration min value", marshaler, &durpb.Duration{Seconds: -315576000000, Nanos: -999999999}, `"-315576000000.999999999s"`},
487	{"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{
488		Fields: map[string]*stpb.Value{
489			"one": {Kind: &stpb.Value_StringValue{"loneliest number"}},
490			"two": {Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}},
491		},
492	}}, `{"st":{"one":"loneliest number","two":null}}`},
493	{"empty ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{}}, `{"lv":[]}`},
494	{"basic ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
495		{Kind: &stpb.Value_StringValue{"x"}},
496		{Kind: &stpb.Value_NullValue{}},
497		{Kind: &stpb.Value_NumberValue{3}},
498		{Kind: &stpb.Value_BoolValue{true}},
499	}}}, `{"lv":["x",null,3,true]}`},
500	{"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
501	{"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}, `{"ts":"2014-05-13T16:53:20Z"}`},
502	{"number Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}, `{"val":1}`},
503	{"null Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}, `{"val":null}`},
504	{"string number value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}, `{"val":"9223372036854775807"}`},
505	{"list of lists Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{
506		Kind: &stpb.Value_ListValue{&stpb.ListValue{
507			Values: []*stpb.Value{
508				{Kind: &stpb.Value_StringValue{"x"}},
509				{Kind: &stpb.Value_ListValue{&stpb.ListValue{
510					Values: []*stpb.Value{
511						{Kind: &stpb.Value_ListValue{&stpb.ListValue{
512							Values: []*stpb.Value{{Kind: &stpb.Value_StringValue{"y"}}},
513						}}},
514						{Kind: &stpb.Value_StringValue{"z"}},
515					},
516				}}},
517			},
518		}},
519	}}, `{"val":["x",[["y"],"z"]]}`},
520
521	{"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`},
522	{"FloatValue", marshaler, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`},
523	{"Int64Value", marshaler, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`},
524	{"UInt64Value", marshaler, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`},
525	{"Int32Value", marshaler, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`},
526	{"UInt32Value", marshaler, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`},
527	{"BoolValue", marshaler, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`},
528	{"StringValue", marshaler, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`},
529	{"BytesValue", marshaler, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
530
531	{"required", marshaler, &pb.MsgWithRequired{Str: proto.String("hello")}, `{"str":"hello"}`},
532	{"required bytes", marshaler, &pb.MsgWithRequiredBytes{Byts: []byte{}}, `{"byts":""}`},
533}
534
535func TestMarshaling(t *testing.T) {
536	for _, tt := range marshalingTests {
537		json, err := tt.marshaler.MarshalToString(tt.pb)
538		if err != nil {
539			t.Errorf("%s: marshaling error: %v", tt.desc, err)
540		} else if tt.json != json {
541			t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json)
542		}
543	}
544}
545
546func TestMarshalingNil(t *testing.T) {
547	var msg *pb.Simple
548	m := &Marshaler{}
549	if _, err := m.MarshalToString(msg); err == nil {
550		t.Errorf("mashaling nil returned no error")
551	}
552}
553
554func TestMarshalIllegalTime(t *testing.T) {
555	tests := []struct {
556		pb   proto.Message
557		fail bool
558	}{
559		{&durpb.Duration{Seconds: 1, Nanos: 0}, false},
560		{&durpb.Duration{Seconds: -1, Nanos: 0}, false},
561		{&durpb.Duration{Seconds: 1, Nanos: -1}, true},
562		{&durpb.Duration{Seconds: -1, Nanos: 1}, true},
563		{&durpb.Duration{Seconds: 315576000001}, true},
564		{&durpb.Duration{Seconds: -315576000001}, true},
565		{&durpb.Duration{Seconds: 1, Nanos: 1000000000}, true},
566		{&durpb.Duration{Seconds: -1, Nanos: -1000000000}, true},
567		{&tspb.Timestamp{Seconds: 1, Nanos: 1}, false},
568		{&tspb.Timestamp{Seconds: 1, Nanos: -1}, true},
569		{&tspb.Timestamp{Seconds: 1, Nanos: 1000000000}, true},
570	}
571	for _, tt := range tests {
572		_, err := marshaler.MarshalToString(tt.pb)
573		if err == nil && tt.fail {
574			t.Errorf("marshaler.MarshalToString(%v) = _, <nil>; want _, <non-nil>", tt.pb)
575		}
576		if err != nil && !tt.fail {
577			t.Errorf("marshaler.MarshalToString(%v) = _, %v; want _, <nil>", tt.pb, err)
578		}
579	}
580}
581
582func TestMarshalJSONPBMarshaler(t *testing.T) {
583	rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
584	msg := dynamicMessage{RawJson: rawJson}
585	str, err := new(Marshaler).MarshalToString(&msg)
586	if err != nil {
587		t.Errorf("an unexpected error occurred when marshalling JSONPBMarshaler: %v", err)
588	}
589	if str != rawJson {
590		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, rawJson)
591	}
592}
593
594func TestMarshalAnyJSONPBMarshaler(t *testing.T) {
595	msg := dynamicMessage{RawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`}
596	a, err := ptypes.MarshalAny(&msg)
597	if err != nil {
598		t.Errorf("an unexpected error occurred when marshalling to Any: %v", err)
599	}
600	str, err := new(Marshaler).MarshalToString(a)
601	if err != nil {
602		t.Errorf("an unexpected error occurred when marshalling Any to JSON: %v", err)
603	}
604	// after custom marshaling, it's round-tripped through JSON decoding/encoding already,
605	// so the keys are sorted, whitespace is compacted, and "@type" key has been added
606	expected := `{"@type":"type.googleapis.com/` + dynamicMessageName + `","baz":[0,1,2,3],"foo":"bar"}`
607	if str != expected {
608		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected)
609	}
610
611	// Do it again, but this time with indentation:
612
613	marshaler := Marshaler{Indent: "  "}
614	str, err = marshaler.MarshalToString(a)
615	if err != nil {
616		t.Errorf("an unexpected error occurred when marshalling Any to JSON: %v", err)
617	}
618	// same as expected above, but pretty-printed w/ indentation
619	expected = `{
620  "@type": "type.googleapis.com/` + dynamicMessageName + `",
621  "baz": [
622    0,
623    1,
624    2,
625    3
626  ],
627  "foo": "bar"
628}`
629	if str != expected {
630		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected)
631	}
632}
633
634func TestMarshalWithCustomValidation(t *testing.T) {
635	msg := dynamicMessage{RawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`, Dummy: &dynamicMessage{}}
636
637	js, err := new(Marshaler).MarshalToString(&msg)
638	if err != nil {
639		t.Errorf("an unexpected error occurred when marshalling to json: %v", err)
640	}
641	err = Unmarshal(strings.NewReader(js), &msg)
642	if err != nil {
643		t.Errorf("an unexpected error occurred when unmarshalling from json: %v", err)
644	}
645}
646
647// Test marshaling message containing unset required fields should produce error.
648func TestMarshalUnsetRequiredFields(t *testing.T) {
649	msgExt := &pb.Real{}
650	proto.SetExtension(msgExt, pb.E_Extm, &pb.MsgWithRequired{})
651
652	tests := []struct {
653		desc      string
654		marshaler *Marshaler
655		pb        proto.Message
656	}{
657		{
658			desc:      "direct required field",
659			marshaler: &Marshaler{},
660			pb:        &pb.MsgWithRequired{},
661		},
662		{
663			desc:      "direct required field + emit defaults",
664			marshaler: &Marshaler{EmitDefaults: true},
665			pb:        &pb.MsgWithRequired{},
666		},
667		{
668			desc:      "indirect required field",
669			marshaler: &Marshaler{},
670			pb:        &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
671		},
672		{
673			desc:      "indirect required field + emit defaults",
674			marshaler: &Marshaler{EmitDefaults: true},
675			pb:        &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
676		},
677		{
678			desc:      "direct required wkt field",
679			marshaler: &Marshaler{},
680			pb:        &pb.MsgWithRequiredWKT{},
681		},
682		{
683			desc:      "direct required wkt field + emit defaults",
684			marshaler: &Marshaler{EmitDefaults: true},
685			pb:        &pb.MsgWithRequiredWKT{},
686		},
687		{
688			desc:      "direct required bytes field",
689			marshaler: &Marshaler{},
690			pb:        &pb.MsgWithRequiredBytes{},
691		},
692		{
693			desc:      "required in map value",
694			marshaler: &Marshaler{},
695			pb: &pb.MsgWithIndirectRequired{
696				MapField: map[string]*pb.MsgWithRequired{
697					"key": {},
698				},
699			},
700		},
701		{
702			desc:      "required in repeated item",
703			marshaler: &Marshaler{},
704			pb: &pb.MsgWithIndirectRequired{
705				SliceField: []*pb.MsgWithRequired{
706					{Str: proto.String("hello")},
707					{},
708				},
709			},
710		},
711		{
712			desc:      "required inside oneof",
713			marshaler: &Marshaler{},
714			pb: &pb.MsgWithOneof{
715				Union: &pb.MsgWithOneof_MsgWithRequired{&pb.MsgWithRequired{}},
716			},
717		},
718		{
719			desc:      "required inside extension",
720			marshaler: &Marshaler{},
721			pb:        msgExt,
722		},
723	}
724
725	for _, tc := range tests {
726		if _, err := tc.marshaler.MarshalToString(tc.pb); err == nil {
727			t.Errorf("%s: expecting error in marshaling with unset required fields %+v", tc.desc, tc.pb)
728		}
729	}
730}
731
732var unmarshalingTests = []struct {
733	desc        string
734	unmarshaler Unmarshaler
735	json        string
736	pb          proto.Message
737}{
738	{"simple flat object", Unmarshaler{}, simpleObjectInputJSON, simpleObject},
739	{"simple pretty object", Unmarshaler{}, simpleObjectInputPrettyJSON, simpleObject},
740	{"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject},
741	{"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
742	{"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
743	{"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
744	{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
745	{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
746	{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
747	{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
748	{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
749	{"unknown enum value object",
750		Unmarshaler{},
751		"{\n  \"color\": 1000,\n  \"r_color\": [\n    \"RED\"\n  ]\n}",
752		&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
753	{"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
754		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
755			proto3pb.Message_PUNS,
756			proto3pb.Message_SLAPSTICK,
757		}}},
758	{"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
759		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
760			proto3pb.Message_PUNS,
761			proto3pb.Message_SLAPSTICK,
762		}}},
763	{"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
764		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
765			proto3pb.Message_PUNS,
766			proto3pb.Message_SLAPSTICK,
767		}}},
768	{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
769	{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
770	{"NaN", Unmarshaler{}, `{"oDouble":"NaN"}`, &pb.Simple{ODouble: proto.Float64(math.NaN())}},
771	{"Inf", Unmarshaler{}, `{"oFloat":"Infinity"}`, &pb.Simple{OFloat: proto.Float32(float32(math.Inf(1)))}},
772	{"-Inf", Unmarshaler{}, `{"oDouble":"-Infinity"}`, &pb.Simple{ODouble: proto.Float64(math.Inf(-1))}},
773	{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
774	{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
775	{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}},
776	{"proto2 extension", Unmarshaler{}, realNumberJSON, realNumber},
777	{"Any with message", Unmarshaler{}, anySimpleJSON, anySimple},
778	{"Any with message and indent", Unmarshaler{}, anySimplePrettyJSON, anySimple},
779	{"Any with WKT", Unmarshaler{}, anyWellKnownJSON, anyWellKnown},
780	{"Any with WKT and indent", Unmarshaler{}, anyWellKnownPrettyJSON, anyWellKnown},
781	{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
782	{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
783	{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
784	{"oneof spec name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
785	{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
786	{"oneof spec name2", Unmarshaler{}, `{"homeAddress":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}},
787	{"oneof orig_name2", Unmarshaler{}, `{"home_address":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}},
788	{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
789	{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
790
791	{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
792	{"Duration", Unmarshaler{}, `{"dur":"4s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 4}}},
793	{"Duration with unicode", Unmarshaler{}, `{"dur": "3\u0073"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
794	{"null Duration", Unmarshaler{}, `{"dur":null}`, &pb.KnownTypes{Dur: nil}},
795	{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
796	{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
797	{"Timestamp with unicode", Unmarshaler{}, `{"ts": "2014-05-13T16:53:20\u005a"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
798	{"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -2, Nanos: 999999995}}},
799	{"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}}},
800	{"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb.KnownTypes{Ts: nil}},
801	{"null Struct", Unmarshaler{}, `{"st": null}`, &pb.KnownTypes{St: nil}},
802	{"empty Struct", Unmarshaler{}, `{"st": {}}`, &pb.KnownTypes{St: &stpb.Struct{}}},
803	{"basic Struct", Unmarshaler{}, `{"st": {"a": "x", "b": null, "c": 3, "d": true}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
804		"a": {Kind: &stpb.Value_StringValue{"x"}},
805		"b": {Kind: &stpb.Value_NullValue{}},
806		"c": {Kind: &stpb.Value_NumberValue{3}},
807		"d": {Kind: &stpb.Value_BoolValue{true}},
808	}}}},
809	{"nested Struct", Unmarshaler{}, `{"st": {"a": {"b": 1, "c": [{"d": true}, "f"]}}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
810		"a": {Kind: &stpb.Value_StructValue{&stpb.Struct{Fields: map[string]*stpb.Value{
811			"b": {Kind: &stpb.Value_NumberValue{1}},
812			"c": {Kind: &stpb.Value_ListValue{&stpb.ListValue{Values: []*stpb.Value{
813				{Kind: &stpb.Value_StructValue{&stpb.Struct{Fields: map[string]*stpb.Value{"d": {Kind: &stpb.Value_BoolValue{true}}}}}},
814				{Kind: &stpb.Value_StringValue{"f"}},
815			}}}},
816		}}}},
817	}}}},
818	{"null ListValue", Unmarshaler{}, `{"lv": null}`, &pb.KnownTypes{Lv: nil}},
819	{"empty ListValue", Unmarshaler{}, `{"lv": []}`, &pb.KnownTypes{Lv: &stpb.ListValue{}}},
820	{"basic ListValue", Unmarshaler{}, `{"lv": ["x", null, 3, true]}`, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
821		{Kind: &stpb.Value_StringValue{"x"}},
822		{Kind: &stpb.Value_NullValue{}},
823		{Kind: &stpb.Value_NumberValue{3}},
824		{Kind: &stpb.Value_BoolValue{true}},
825	}}}},
826	{"number Value", Unmarshaler{}, `{"val":1}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}},
827	{"null Value", Unmarshaler{}, `{"val":null}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}},
828	{"bool Value", Unmarshaler{}, `{"val":true}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_BoolValue{true}}}},
829	{"string Value", Unmarshaler{}, `{"val":"x"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"x"}}}},
830	{"string number value", Unmarshaler{}, `{"val":"9223372036854775807"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}},
831	{"list of lists Value", Unmarshaler{}, `{"val":["x", [["y"], "z"]]}`, &pb.KnownTypes{Val: &stpb.Value{
832		Kind: &stpb.Value_ListValue{&stpb.ListValue{
833			Values: []*stpb.Value{
834				{Kind: &stpb.Value_StringValue{"x"}},
835				{Kind: &stpb.Value_ListValue{&stpb.ListValue{
836					Values: []*stpb.Value{
837						{Kind: &stpb.Value_ListValue{&stpb.ListValue{
838							Values: []*stpb.Value{{Kind: &stpb.Value_StringValue{"y"}}},
839						}}},
840						{Kind: &stpb.Value_StringValue{"z"}},
841					},
842				}}},
843			},
844		}}}}},
845
846	{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
847	{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
848	{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
849	{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
850	{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
851	{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
852	{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
853	{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
854	{"StringValue containing escaped character", Unmarshaler{}, `{"str":"a\/b"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "a/b"}}},
855	{"StructValue containing StringValue's", Unmarshaler{}, `{"escaped": "a\/b", "unicode": "\u00004E16\u0000754C"}`,
856		&stpb.Struct{
857			Fields: map[string]*stpb.Value{
858				"escaped": {Kind: &stpb.Value_StringValue{"a/b"}},
859				"unicode": {Kind: &stpb.Value_StringValue{"\u00004E16\u0000754C"}},
860			},
861		}},
862	{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
863
864	// Ensure that `null` as a value ends up with a nil pointer instead of a [type]Value struct.
865	{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: nil}},
866	{"null FloatValue", Unmarshaler{}, `{"flt":null}`, &pb.KnownTypes{Flt: nil}},
867	{"null Int64Value", Unmarshaler{}, `{"i64":null}`, &pb.KnownTypes{I64: nil}},
868	{"null UInt64Value", Unmarshaler{}, `{"u64":null}`, &pb.KnownTypes{U64: nil}},
869	{"null Int32Value", Unmarshaler{}, `{"i32":null}`, &pb.KnownTypes{I32: nil}},
870	{"null UInt32Value", Unmarshaler{}, `{"u32":null}`, &pb.KnownTypes{U32: nil}},
871	{"null BoolValue", Unmarshaler{}, `{"bool":null}`, &pb.KnownTypes{Bool: nil}},
872	{"null StringValue", Unmarshaler{}, `{"str":null}`, &pb.KnownTypes{Str: nil}},
873	{"null BytesValue", Unmarshaler{}, `{"bytes":null}`, &pb.KnownTypes{Bytes: nil}},
874
875	{"required", Unmarshaler{}, `{"str":"hello"}`, &pb.MsgWithRequired{Str: proto.String("hello")}},
876	{"required bytes", Unmarshaler{}, `{"byts": []}`, &pb.MsgWithRequiredBytes{Byts: []byte{}}},
877}
878
879func TestUnmarshaling(t *testing.T) {
880	for _, tt := range unmarshalingTests {
881		// Make a new instance of the type of our expected object.
882		p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
883
884		err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p)
885		if err != nil {
886			t.Errorf("unmarshalling %s: %v", tt.desc, err)
887			continue
888		}
889
890		// For easier diffs, compare text strings of the protos.
891		exp := proto.MarshalTextString(tt.pb)
892		act := proto.MarshalTextString(p)
893		if string(exp) != string(act) {
894			t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
895		}
896	}
897}
898
899func TestUnmarshalNullArray(t *testing.T) {
900	var repeats pb.Repeats
901	if err := UnmarshalString(`{"rBool":null}`, &repeats); err != nil {
902		t.Fatal(err)
903	}
904	if !reflect.DeepEqual(repeats, pb.Repeats{}) {
905		t.Errorf("got non-nil fields in [%#v]", repeats)
906	}
907}
908
909func TestUnmarshalNullObject(t *testing.T) {
910	var maps pb.Maps
911	if err := UnmarshalString(`{"mInt64Str":null}`, &maps); err != nil {
912		t.Fatal(err)
913	}
914	if !reflect.DeepEqual(maps, pb.Maps{}) {
915		t.Errorf("got non-nil fields in [%#v]", maps)
916	}
917}
918
919func TestUnmarshalNext(t *testing.T) {
920	// We only need to check against a few, not all of them.
921	tests := unmarshalingTests[:5]
922
923	// Create a buffer with many concatenated JSON objects.
924	var b bytes.Buffer
925	for _, tt := range tests {
926		b.WriteString(tt.json)
927	}
928
929	dec := json.NewDecoder(&b)
930	for _, tt := range tests {
931		// Make a new instance of the type of our expected object.
932		p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
933
934		err := tt.unmarshaler.UnmarshalNext(dec, p)
935		if err != nil {
936			t.Errorf("%s: %v", tt.desc, err)
937			continue
938		}
939
940		// For easier diffs, compare text strings of the protos.
941		exp := proto.MarshalTextString(tt.pb)
942		act := proto.MarshalTextString(p)
943		if string(exp) != string(act) {
944			t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
945		}
946	}
947
948	p := &pb.Simple{}
949	err := new(Unmarshaler).UnmarshalNext(dec, p)
950	if err != io.EOF {
951		t.Errorf("eof: got %v, expected io.EOF", err)
952	}
953}
954
955var unmarshalingShouldError = []struct {
956	desc string
957	in   string
958	pb   proto.Message
959}{
960	{"a value", "666", new(pb.Simple)},
961	{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
962	{"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
963	{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
964	{"Duration containing invalid character", `{"dur": "3\U0073"}`, &pb.KnownTypes{}},
965	{"Timestamp containing invalid character", `{"ts": "2014-05-13T16:53:20\U005a"}`, &pb.KnownTypes{}},
966	{"StringValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &pb.KnownTypes{}},
967	{"StructValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &stpb.Struct{}},
968	{"repeated proto3 enum with non array input", `{"rFunny":"PUNS"}`, &proto3pb.Message{RFunny: []proto3pb.Message_Humour{}}},
969}
970
971func TestUnmarshalingBadInput(t *testing.T) {
972	for _, tt := range unmarshalingShouldError {
973		err := UnmarshalString(tt.in, tt.pb)
974		if err == nil {
975			t.Errorf("an error was expected when parsing %q instead of an object", tt.desc)
976		}
977	}
978}
979
980type funcResolver func(turl string) (proto.Message, error)
981
982func (fn funcResolver) Resolve(turl string) (proto.Message, error) {
983	return fn(turl)
984}
985
986func TestAnyWithCustomResolver(t *testing.T) {
987	var resolvedTypeUrls []string
988	resolver := funcResolver(func(turl string) (proto.Message, error) {
989		resolvedTypeUrls = append(resolvedTypeUrls, turl)
990		return new(pb.Simple), nil
991	})
992	msg := &pb.Simple{
993		OBytes:  []byte{1, 2, 3, 4},
994		OBool:   proto.Bool(true),
995		OString: proto.String("foobar"),
996		OInt64:  proto.Int64(1020304),
997	}
998	msgBytes, err := proto.Marshal(msg)
999	if err != nil {
1000		t.Errorf("an unexpected error occurred when marshaling message: %v", err)
1001	}
1002	// make an Any with a type URL that won't resolve w/out custom resolver
1003	any := &anypb.Any{
1004		TypeUrl: "https://foobar.com/some.random.MessageKind",
1005		Value:   msgBytes,
1006	}
1007
1008	m := Marshaler{AnyResolver: resolver}
1009	js, err := m.MarshalToString(any)
1010	if err != nil {
1011		t.Errorf("an unexpected error occurred when marshaling any to JSON: %v", err)
1012	}
1013	if len(resolvedTypeUrls) != 1 {
1014		t.Errorf("custom resolver was not invoked during marshaling")
1015	} else if resolvedTypeUrls[0] != "https://foobar.com/some.random.MessageKind" {
1016		t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[0], "https://foobar.com/some.random.MessageKind")
1017	}
1018	wanted := `{"@type":"https://foobar.com/some.random.MessageKind","oBool":true,"oInt64":"1020304","oString":"foobar","oBytes":"AQIDBA=="}`
1019	if js != wanted {
1020		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", js, wanted)
1021	}
1022
1023	u := Unmarshaler{AnyResolver: resolver}
1024	roundTrip := &anypb.Any{}
1025	err = u.Unmarshal(bytes.NewReader([]byte(js)), roundTrip)
1026	if err != nil {
1027		t.Errorf("an unexpected error occurred when unmarshaling any from JSON: %v", err)
1028	}
1029	if len(resolvedTypeUrls) != 2 {
1030		t.Errorf("custom resolver was not invoked during marshaling")
1031	} else if resolvedTypeUrls[1] != "https://foobar.com/some.random.MessageKind" {
1032		t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[1], "https://foobar.com/some.random.MessageKind")
1033	}
1034	if !proto.Equal(any, roundTrip) {
1035		t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", roundTrip, any)
1036	}
1037}
1038
1039func TestUnmarshalJSONPBUnmarshaler(t *testing.T) {
1040	rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
1041	var msg dynamicMessage
1042	if err := Unmarshal(strings.NewReader(rawJson), &msg); err != nil {
1043		t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err)
1044	}
1045	if msg.RawJson != rawJson {
1046		t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", msg.RawJson, rawJson)
1047	}
1048}
1049
1050func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
1051	rawJson := `{"stringField":null}`
1052	var ptrFieldMsg ptrFieldMessage
1053	if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil {
1054		t.Errorf("unmarshal error: %v", err)
1055	}
1056
1057	want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}}
1058	if !proto.Equal(&ptrFieldMsg, &want) {
1059		t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want)
1060	}
1061}
1062
1063func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
1064	rawJson := `{ "@type": "blah.com/` + dynamicMessageName + `", "foo": "bar", "baz": [0, 1, 2, 3] }`
1065	var got anypb.Any
1066	if err := Unmarshal(strings.NewReader(rawJson), &got); err != nil {
1067		t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err)
1068	}
1069
1070	dm := &dynamicMessage{RawJson: `{"baz":[0,1,2,3],"foo":"bar"}`}
1071	var want anypb.Any
1072	if b, err := proto.Marshal(dm); err != nil {
1073		t.Errorf("an unexpected error occurred when marshaling message: %v", err)
1074	} else {
1075		want.TypeUrl = "blah.com/" + dynamicMessageName
1076		want.Value = b
1077	}
1078
1079	if !proto.Equal(&got, &want) {
1080		t.Errorf("message contents not set correctly after unmarshalling JSON: got %v, wanted %v", got, want)
1081	}
1082}
1083
1084const (
1085	dynamicMessageName = "google.protobuf.jsonpb.testing.dynamicMessage"
1086)
1087
1088func init() {
1089	// we register the custom type below so that we can use it in Any types
1090	proto.RegisterType((*dynamicMessage)(nil), dynamicMessageName)
1091}
1092
1093type ptrFieldMessage struct {
1094	StringField *stringField `protobuf:"bytes,1,opt,name=stringField"`
1095}
1096
1097func (m *ptrFieldMessage) Reset() {
1098}
1099
1100func (m *ptrFieldMessage) String() string {
1101	return m.StringField.StringValue
1102}
1103
1104func (m *ptrFieldMessage) ProtoMessage() {
1105}
1106
1107type stringField struct {
1108	IsSet       bool   `protobuf:"varint,1,opt,name=isSet"`
1109	StringValue string `protobuf:"bytes,2,opt,name=stringValue"`
1110}
1111
1112func (s *stringField) Reset() {
1113}
1114
1115func (s *stringField) String() string {
1116	return s.StringValue
1117}
1118
1119func (s *stringField) ProtoMessage() {
1120}
1121
1122func (s *stringField) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
1123	s.IsSet = true
1124	s.StringValue = string(js)
1125	return nil
1126}
1127
1128// dynamicMessage implements protobuf.Message but is not a normal generated message type.
1129// It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support.
1130type dynamicMessage struct {
1131	RawJson string `protobuf:"bytes,1,opt,name=rawJson"`
1132
1133	// an unexported nested message is present just to ensure that it
1134	// won't result in a panic (see issue #509)
1135	Dummy *dynamicMessage `protobuf:"bytes,2,opt,name=dummy"`
1136}
1137
1138func (m *dynamicMessage) Reset() {
1139	m.RawJson = "{}"
1140}
1141
1142func (m *dynamicMessage) String() string {
1143	return m.RawJson
1144}
1145
1146func (m *dynamicMessage) ProtoMessage() {
1147}
1148
1149func (m *dynamicMessage) MarshalJSONPB(jm *Marshaler) ([]byte, error) {
1150	return []byte(m.RawJson), nil
1151}
1152
1153func (m *dynamicMessage) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
1154	m.RawJson = string(js)
1155	return nil
1156}
1157
1158// Test unmarshaling message containing unset required fields should produce error.
1159func TestUnmarshalUnsetRequiredFields(t *testing.T) {
1160	tests := []struct {
1161		desc string
1162		pb   proto.Message
1163		json string
1164	}{
1165		{
1166			desc: "direct required field missing",
1167			pb:   &pb.MsgWithRequired{},
1168			json: `{}`,
1169		},
1170		{
1171			desc: "direct required field set to null",
1172			pb:   &pb.MsgWithRequired{},
1173			json: `{"str": null}`,
1174		},
1175		{
1176			desc: "indirect required field missing",
1177			pb:   &pb.MsgWithIndirectRequired{},
1178			json: `{"subm": {}}`,
1179		},
1180		{
1181			desc: "indirect required field set to null",
1182			pb:   &pb.MsgWithIndirectRequired{},
1183			json: `{"subm": {"str": null}}`,
1184		},
1185		{
1186			desc: "direct required bytes field missing",
1187			pb:   &pb.MsgWithRequiredBytes{},
1188			json: `{}`,
1189		},
1190		{
1191			desc: "direct required bytes field set to null",
1192			pb:   &pb.MsgWithRequiredBytes{},
1193			json: `{"byts": null}`,
1194		},
1195		{
1196			desc: "direct required wkt field missing",
1197			pb:   &pb.MsgWithRequiredWKT{},
1198			json: `{}`,
1199		},
1200		{
1201			desc: "direct required wkt field set to null",
1202			pb:   &pb.MsgWithRequiredWKT{},
1203			json: `{"str": null}`,
1204		},
1205		{
1206			desc: "any containing message with required field set to null",
1207			pb:   &pb.KnownTypes{},
1208			json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired", "str": null}}`,
1209		},
1210		{
1211			desc: "any containing message with missing required field",
1212			pb:   &pb.KnownTypes{},
1213			json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired"}}`,
1214		},
1215		{
1216			desc: "missing required in map value",
1217			pb:   &pb.MsgWithIndirectRequired{},
1218			json: `{"map_field": {"a": {}, "b": {"str": "hi"}}}`,
1219		},
1220		{
1221			desc: "required in map value set to null",
1222			pb:   &pb.MsgWithIndirectRequired{},
1223			json: `{"map_field": {"a": {"str": "hello"}, "b": {"str": null}}}`,
1224		},
1225		{
1226			desc: "missing required in slice item",
1227			pb:   &pb.MsgWithIndirectRequired{},
1228			json: `{"slice_field": [{}, {"str": "hi"}]}`,
1229		},
1230		{
1231			desc: "required in slice item set to null",
1232			pb:   &pb.MsgWithIndirectRequired{},
1233			json: `{"slice_field": [{"str": "hello"}, {"str": null}]}`,
1234		},
1235		{
1236			desc: "required inside oneof missing",
1237			pb:   &pb.MsgWithOneof{},
1238			json: `{"msgWithRequired": {}}`,
1239		},
1240		{
1241			desc: "required inside oneof set to null",
1242			pb:   &pb.MsgWithOneof{},
1243			json: `{"msgWithRequired": {"str": null}}`,
1244		},
1245		{
1246			desc: "required field in extension missing",
1247			pb:   &pb.Real{},
1248			json: `{"[jsonpb.extm]":{}}`,
1249		},
1250		{
1251			desc: "required field in extension set to null",
1252			pb:   &pb.Real{},
1253			json: `{"[jsonpb.extm]":{"str": null}}`,
1254		},
1255	}
1256
1257	for _, tc := range tests {
1258		if err := UnmarshalString(tc.json, tc.pb); err == nil {
1259			t.Errorf("%s: expecting error in unmarshaling with unset required fields %s", tc.desc, tc.json)
1260		}
1261	}
1262}
1263