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", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}, `{"dur":"3s"}`},
477	{"Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3, Nanos: 1e6}}, `{"dur":"3.001s"}`},
478	{"Duration beyond float64 precision", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 100000000, Nanos: 1}}, `{"dur":"100000000.000000001s"}`},
479	{"negative Duration", marshaler, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: -123, Nanos: -456}}, `{"dur":"-123.000000456s"}`},
480	{"Struct", marshaler, &pb.KnownTypes{St: &stpb.Struct{
481		Fields: map[string]*stpb.Value{
482			"one": {Kind: &stpb.Value_StringValue{"loneliest number"}},
483			"two": {Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}},
484		},
485	}}, `{"st":{"one":"loneliest number","two":null}}`},
486	{"empty ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{}}, `{"lv":[]}`},
487	{"basic ListValue", marshaler, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
488		{Kind: &stpb.Value_StringValue{"x"}},
489		{Kind: &stpb.Value_NullValue{}},
490		{Kind: &stpb.Value_NumberValue{3}},
491		{Kind: &stpb.Value_BoolValue{true}},
492	}}}, `{"lv":["x",null,3,true]}`},
493	{"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}, `{"ts":"2014-05-13T16:53:20.021Z"}`},
494	{"Timestamp", marshaler, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}, `{"ts":"2014-05-13T16:53:20Z"}`},
495	{"number Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}, `{"val":1}`},
496	{"null Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}, `{"val":null}`},
497	{"string number value", marshaler, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}, `{"val":"9223372036854775807"}`},
498	{"list of lists Value", marshaler, &pb.KnownTypes{Val: &stpb.Value{
499		Kind: &stpb.Value_ListValue{&stpb.ListValue{
500			Values: []*stpb.Value{
501				{Kind: &stpb.Value_StringValue{"x"}},
502				{Kind: &stpb.Value_ListValue{&stpb.ListValue{
503					Values: []*stpb.Value{
504						{Kind: &stpb.Value_ListValue{&stpb.ListValue{
505							Values: []*stpb.Value{{Kind: &stpb.Value_StringValue{"y"}}},
506						}}},
507						{Kind: &stpb.Value_StringValue{"z"}},
508					},
509				}}},
510			},
511		}},
512	}}, `{"val":["x",[["y"],"z"]]}`},
513
514	{"DoubleValue", marshaler, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}, `{"dbl":1.2}`},
515	{"FloatValue", marshaler, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}, `{"flt":1.2}`},
516	{"Int64Value", marshaler, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}, `{"i64":"-3"}`},
517	{"UInt64Value", marshaler, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}, `{"u64":"3"}`},
518	{"Int32Value", marshaler, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}, `{"i32":-4}`},
519	{"UInt32Value", marshaler, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}, `{"u32":4}`},
520	{"BoolValue", marshaler, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}, `{"bool":true}`},
521	{"StringValue", marshaler, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}, `{"str":"plush"}`},
522	{"BytesValue", marshaler, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}, `{"bytes":"d293"}`},
523
524	{"required", marshaler, &pb.MsgWithRequired{Str: proto.String("hello")}, `{"str":"hello"}`},
525	{"required bytes", marshaler, &pb.MsgWithRequiredBytes{Byts: []byte{}}, `{"byts":""}`},
526}
527
528func TestMarshaling(t *testing.T) {
529	for _, tt := range marshalingTests {
530		json, err := tt.marshaler.MarshalToString(tt.pb)
531		if err != nil {
532			t.Errorf("%s: marshaling error: %v", tt.desc, err)
533		} else if tt.json != json {
534			t.Errorf("%s: got [%v] want [%v]", tt.desc, json, tt.json)
535		}
536	}
537}
538
539func TestMarshalingNil(t *testing.T) {
540	var msg *pb.Simple
541	m := &Marshaler{}
542	if _, err := m.MarshalToString(msg); err == nil {
543		t.Errorf("mashaling nil returned no error")
544	}
545}
546
547func TestMarshalIllegalTime(t *testing.T) {
548	tests := []struct {
549		pb   proto.Message
550		fail bool
551	}{
552		{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 0}}, false},
553		{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 0}}, false},
554		{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: -1}}, true},
555		{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: 1}}, true},
556		{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: 1, Nanos: 1000000000}}, true},
557		{&pb.KnownTypes{Dur: &durpb.Duration{Seconds: -1, Nanos: -1000000000}}, true},
558		{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1}}, false},
559		{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: -1}}, true},
560		{&pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 1, Nanos: 1000000000}}, true},
561	}
562	for _, tt := range tests {
563		_, err := marshaler.MarshalToString(tt.pb)
564		if err == nil && tt.fail {
565			t.Errorf("marshaler.MarshalToString(%v) = _, <nil>; want _, <non-nil>", tt.pb)
566		}
567		if err != nil && !tt.fail {
568			t.Errorf("marshaler.MarshalToString(%v) = _, %v; want _, <nil>", tt.pb, err)
569		}
570	}
571}
572
573func TestMarshalJSONPBMarshaler(t *testing.T) {
574	rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
575	msg := dynamicMessage{RawJson: rawJson}
576	str, err := new(Marshaler).MarshalToString(&msg)
577	if err != nil {
578		t.Errorf("an unexpected error occurred when marshalling JSONPBMarshaler: %v", err)
579	}
580	if str != rawJson {
581		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, rawJson)
582	}
583}
584
585func TestMarshalAnyJSONPBMarshaler(t *testing.T) {
586	msg := dynamicMessage{RawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`}
587	a, err := ptypes.MarshalAny(&msg)
588	if err != nil {
589		t.Errorf("an unexpected error occurred when marshalling to Any: %v", err)
590	}
591	str, err := new(Marshaler).MarshalToString(a)
592	if err != nil {
593		t.Errorf("an unexpected error occurred when marshalling Any to JSON: %v", err)
594	}
595	// after custom marshaling, it's round-tripped through JSON decoding/encoding already,
596	// so the keys are sorted, whitespace is compacted, and "@type" key has been added
597	expected := `{"@type":"type.googleapis.com/` + dynamicMessageName + `","baz":[0,1,2,3],"foo":"bar"}`
598	if str != expected {
599		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", str, expected)
600	}
601}
602
603func TestMarshalWithCustomValidation(t *testing.T) {
604	msg := dynamicMessage{RawJson: `{ "foo": "bar", "baz": [0, 1, 2, 3] }`, Dummy: &dynamicMessage{}}
605
606	js, err := new(Marshaler).MarshalToString(&msg)
607	if err != nil {
608		t.Errorf("an unexpected error occurred when marshalling to json: %v", err)
609	}
610	err = Unmarshal(strings.NewReader(js), &msg)
611	if err != nil {
612		t.Errorf("an unexpected error occurred when unmarshalling from json: %v", err)
613	}
614}
615
616// Test marshaling message containing unset required fields should produce error.
617func TestMarshalUnsetRequiredFields(t *testing.T) {
618	msgExt := &pb.Real{}
619	proto.SetExtension(msgExt, pb.E_Extm, &pb.MsgWithRequired{})
620
621	tests := []struct {
622		desc      string
623		marshaler *Marshaler
624		pb        proto.Message
625	}{
626		{
627			desc:      "direct required field",
628			marshaler: &Marshaler{},
629			pb:        &pb.MsgWithRequired{},
630		},
631		{
632			desc:      "direct required field + emit defaults",
633			marshaler: &Marshaler{EmitDefaults: true},
634			pb:        &pb.MsgWithRequired{},
635		},
636		{
637			desc:      "indirect required field",
638			marshaler: &Marshaler{},
639			pb:        &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
640		},
641		{
642			desc:      "indirect required field + emit defaults",
643			marshaler: &Marshaler{EmitDefaults: true},
644			pb:        &pb.MsgWithIndirectRequired{Subm: &pb.MsgWithRequired{}},
645		},
646		{
647			desc:      "direct required wkt field",
648			marshaler: &Marshaler{},
649			pb:        &pb.MsgWithRequiredWKT{},
650		},
651		{
652			desc:      "direct required wkt field + emit defaults",
653			marshaler: &Marshaler{EmitDefaults: true},
654			pb:        &pb.MsgWithRequiredWKT{},
655		},
656		{
657			desc:      "direct required bytes field",
658			marshaler: &Marshaler{},
659			pb:        &pb.MsgWithRequiredBytes{},
660		},
661		{
662			desc:      "required in map value",
663			marshaler: &Marshaler{},
664			pb: &pb.MsgWithIndirectRequired{
665				MapField: map[string]*pb.MsgWithRequired{
666					"key": {},
667				},
668			},
669		},
670		{
671			desc:      "required in repeated item",
672			marshaler: &Marshaler{},
673			pb: &pb.MsgWithIndirectRequired{
674				SliceField: []*pb.MsgWithRequired{
675					{Str: proto.String("hello")},
676					{},
677				},
678			},
679		},
680		{
681			desc:      "required inside oneof",
682			marshaler: &Marshaler{},
683			pb: &pb.MsgWithOneof{
684				Union: &pb.MsgWithOneof_MsgWithRequired{&pb.MsgWithRequired{}},
685			},
686		},
687		{
688			desc:      "required inside extension",
689			marshaler: &Marshaler{},
690			pb:        msgExt,
691		},
692	}
693
694	for _, tc := range tests {
695		if _, err := tc.marshaler.MarshalToString(tc.pb); err == nil {
696			t.Errorf("%s: expecting error in marshaling with unset required fields %+v", tc.desc, tc.pb)
697		}
698	}
699}
700
701var unmarshalingTests = []struct {
702	desc        string
703	unmarshaler Unmarshaler
704	json        string
705	pb          proto.Message
706}{
707	{"simple flat object", Unmarshaler{}, simpleObjectInputJSON, simpleObject},
708	{"simple pretty object", Unmarshaler{}, simpleObjectInputPrettyJSON, simpleObject},
709	{"repeated fields flat object", Unmarshaler{}, repeatsObjectJSON, repeatsObject},
710	{"repeated fields pretty object", Unmarshaler{}, repeatsObjectPrettyJSON, repeatsObject},
711	{"nested message/enum flat object", Unmarshaler{}, complexObjectJSON, complexObject},
712	{"nested message/enum pretty object", Unmarshaler{}, complexObjectPrettyJSON, complexObject},
713	{"enum-string object", Unmarshaler{}, `{"color":"BLUE"}`, &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
714	{"enum-value object", Unmarshaler{}, "{\n \"color\": 2\n}", &pb.Widget{Color: pb.Widget_BLUE.Enum()}},
715	{"unknown field with allowed option", Unmarshaler{AllowUnknownFields: true}, `{"unknown": "foo"}`, new(pb.Simple)},
716	{"proto3 enum string", Unmarshaler{}, `{"hilarity":"PUNS"}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
717	{"proto3 enum value", Unmarshaler{}, `{"hilarity":1}`, &proto3pb.Message{Hilarity: proto3pb.Message_PUNS}},
718	{"unknown enum value object",
719		Unmarshaler{},
720		"{\n  \"color\": 1000,\n  \"r_color\": [\n    \"RED\"\n  ]\n}",
721		&pb.Widget{Color: pb.Widget_Color(1000).Enum(), RColor: []pb.Widget_Color{pb.Widget_RED}}},
722	{"repeated proto3 enum", Unmarshaler{}, `{"rFunny":["PUNS","SLAPSTICK"]}`,
723		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
724			proto3pb.Message_PUNS,
725			proto3pb.Message_SLAPSTICK,
726		}}},
727	{"repeated proto3 enum as int", Unmarshaler{}, `{"rFunny":[1,2]}`,
728		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
729			proto3pb.Message_PUNS,
730			proto3pb.Message_SLAPSTICK,
731		}}},
732	{"repeated proto3 enum as mix of strings and ints", Unmarshaler{}, `{"rFunny":["PUNS",2]}`,
733		&proto3pb.Message{RFunny: []proto3pb.Message_Humour{
734			proto3pb.Message_PUNS,
735			proto3pb.Message_SLAPSTICK,
736		}}},
737	{"unquoted int64 object", Unmarshaler{}, `{"oInt64":-314}`, &pb.Simple{OInt64: proto.Int64(-314)}},
738	{"unquoted uint64 object", Unmarshaler{}, `{"oUint64":123}`, &pb.Simple{OUint64: proto.Uint64(123)}},
739	{"NaN", Unmarshaler{}, `{"oDouble":"NaN"}`, &pb.Simple{ODouble: proto.Float64(math.NaN())}},
740	{"Inf", Unmarshaler{}, `{"oFloat":"Infinity"}`, &pb.Simple{OFloat: proto.Float32(float32(math.Inf(1)))}},
741	{"-Inf", Unmarshaler{}, `{"oDouble":"-Infinity"}`, &pb.Simple{ODouble: proto.Float64(math.Inf(-1))}},
742	{"map<int64, int32>", Unmarshaler{}, `{"nummy":{"1":2,"3":4}}`, &pb.Mappy{Nummy: map[int64]int32{1: 2, 3: 4}}},
743	{"map<string, string>", Unmarshaler{}, `{"strry":{"\"one\"":"two","three":"four"}}`, &pb.Mappy{Strry: map[string]string{`"one"`: "two", "three": "four"}}},
744	{"map<int32, Object>", Unmarshaler{}, `{"objjy":{"1":{"dub":1}}}`, &pb.Mappy{Objjy: map[int32]*pb.Simple3{1: {Dub: 1}}}},
745	{"proto2 extension", Unmarshaler{}, realNumberJSON, realNumber},
746	{"Any with message", Unmarshaler{}, anySimpleJSON, anySimple},
747	{"Any with message and indent", Unmarshaler{}, anySimplePrettyJSON, anySimple},
748	{"Any with WKT", Unmarshaler{}, anyWellKnownJSON, anyWellKnown},
749	{"Any with WKT and indent", Unmarshaler{}, anyWellKnownPrettyJSON, anyWellKnown},
750	{"map<string, enum>", Unmarshaler{}, `{"enumy":{"XIV":"ROMAN"}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
751	{"map<string, enum as int>", Unmarshaler{}, `{"enumy":{"XIV":2}}`, &pb.Mappy{Enumy: map[string]pb.Numeral{"XIV": pb.Numeral_ROMAN}}},
752	{"oneof", Unmarshaler{}, `{"salary":31000}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Salary{31000}}},
753	{"oneof spec name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
754	{"oneof orig_name", Unmarshaler{}, `{"Country":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_Country{"Australia"}}},
755	{"oneof spec name2", Unmarshaler{}, `{"homeAddress":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}},
756	{"oneof orig_name2", Unmarshaler{}, `{"home_address":"Australia"}`, &pb.MsgWithOneof{Union: &pb.MsgWithOneof_HomeAddress{"Australia"}}},
757	{"orig_name input", Unmarshaler{}, `{"o_bool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
758	{"camelName input", Unmarshaler{}, `{"oBool":true}`, &pb.Simple{OBool: proto.Bool(true)}},
759
760	{"Duration", Unmarshaler{}, `{"dur":"3.000s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
761	{"Duration", Unmarshaler{}, `{"dur":"4s"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 4}}},
762	{"Duration with unicode", Unmarshaler{}, `{"dur": "3\u0073"}`, &pb.KnownTypes{Dur: &durpb.Duration{Seconds: 3}}},
763	{"null Duration", Unmarshaler{}, `{"dur":null}`, &pb.KnownTypes{Dur: nil}},
764	{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20.021Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 21e6}}},
765	{"Timestamp", Unmarshaler{}, `{"ts":"2014-05-13T16:53:20Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
766	{"Timestamp with unicode", Unmarshaler{}, `{"ts": "2014-05-13T16:53:20\u005a"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: 14e8, Nanos: 0}}},
767	{"PreEpochTimestamp", Unmarshaler{}, `{"ts":"1969-12-31T23:59:58.999999995Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -2, Nanos: 999999995}}},
768	{"ZeroTimeTimestamp", Unmarshaler{}, `{"ts":"0001-01-01T00:00:00Z"}`, &pb.KnownTypes{Ts: &tspb.Timestamp{Seconds: -62135596800, Nanos: 0}}},
769	{"null Timestamp", Unmarshaler{}, `{"ts":null}`, &pb.KnownTypes{Ts: nil}},
770	{"null Struct", Unmarshaler{}, `{"st": null}`, &pb.KnownTypes{St: nil}},
771	{"empty Struct", Unmarshaler{}, `{"st": {}}`, &pb.KnownTypes{St: &stpb.Struct{}}},
772	{"basic Struct", Unmarshaler{}, `{"st": {"a": "x", "b": null, "c": 3, "d": true}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
773		"a": {Kind: &stpb.Value_StringValue{"x"}},
774		"b": {Kind: &stpb.Value_NullValue{}},
775		"c": {Kind: &stpb.Value_NumberValue{3}},
776		"d": {Kind: &stpb.Value_BoolValue{true}},
777	}}}},
778	{"nested Struct", Unmarshaler{}, `{"st": {"a": {"b": 1, "c": [{"d": true}, "f"]}}}`, &pb.KnownTypes{St: &stpb.Struct{Fields: map[string]*stpb.Value{
779		"a": {Kind: &stpb.Value_StructValue{&stpb.Struct{Fields: map[string]*stpb.Value{
780			"b": {Kind: &stpb.Value_NumberValue{1}},
781			"c": {Kind: &stpb.Value_ListValue{&stpb.ListValue{Values: []*stpb.Value{
782				{Kind: &stpb.Value_StructValue{&stpb.Struct{Fields: map[string]*stpb.Value{"d": {Kind: &stpb.Value_BoolValue{true}}}}}},
783				{Kind: &stpb.Value_StringValue{"f"}},
784			}}}},
785		}}}},
786	}}}},
787	{"null ListValue", Unmarshaler{}, `{"lv": null}`, &pb.KnownTypes{Lv: nil}},
788	{"empty ListValue", Unmarshaler{}, `{"lv": []}`, &pb.KnownTypes{Lv: &stpb.ListValue{}}},
789	{"basic ListValue", Unmarshaler{}, `{"lv": ["x", null, 3, true]}`, &pb.KnownTypes{Lv: &stpb.ListValue{Values: []*stpb.Value{
790		{Kind: &stpb.Value_StringValue{"x"}},
791		{Kind: &stpb.Value_NullValue{}},
792		{Kind: &stpb.Value_NumberValue{3}},
793		{Kind: &stpb.Value_BoolValue{true}},
794	}}}},
795	{"number Value", Unmarshaler{}, `{"val":1}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NumberValue{1}}}},
796	{"null Value", Unmarshaler{}, `{"val":null}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_NullValue{stpb.NullValue_NULL_VALUE}}}},
797	{"bool Value", Unmarshaler{}, `{"val":true}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_BoolValue{true}}}},
798	{"string Value", Unmarshaler{}, `{"val":"x"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"x"}}}},
799	{"string number value", Unmarshaler{}, `{"val":"9223372036854775807"}`, &pb.KnownTypes{Val: &stpb.Value{Kind: &stpb.Value_StringValue{"9223372036854775807"}}}},
800	{"list of lists Value", Unmarshaler{}, `{"val":["x", [["y"], "z"]]}`, &pb.KnownTypes{Val: &stpb.Value{
801		Kind: &stpb.Value_ListValue{&stpb.ListValue{
802			Values: []*stpb.Value{
803				{Kind: &stpb.Value_StringValue{"x"}},
804				{Kind: &stpb.Value_ListValue{&stpb.ListValue{
805					Values: []*stpb.Value{
806						{Kind: &stpb.Value_ListValue{&stpb.ListValue{
807							Values: []*stpb.Value{{Kind: &stpb.Value_StringValue{"y"}}},
808						}}},
809						{Kind: &stpb.Value_StringValue{"z"}},
810					},
811				}}},
812			},
813		}}}}},
814
815	{"DoubleValue", Unmarshaler{}, `{"dbl":1.2}`, &pb.KnownTypes{Dbl: &wpb.DoubleValue{Value: 1.2}}},
816	{"FloatValue", Unmarshaler{}, `{"flt":1.2}`, &pb.KnownTypes{Flt: &wpb.FloatValue{Value: 1.2}}},
817	{"Int64Value", Unmarshaler{}, `{"i64":"-3"}`, &pb.KnownTypes{I64: &wpb.Int64Value{Value: -3}}},
818	{"UInt64Value", Unmarshaler{}, `{"u64":"3"}`, &pb.KnownTypes{U64: &wpb.UInt64Value{Value: 3}}},
819	{"Int32Value", Unmarshaler{}, `{"i32":-4}`, &pb.KnownTypes{I32: &wpb.Int32Value{Value: -4}}},
820	{"UInt32Value", Unmarshaler{}, `{"u32":4}`, &pb.KnownTypes{U32: &wpb.UInt32Value{Value: 4}}},
821	{"BoolValue", Unmarshaler{}, `{"bool":true}`, &pb.KnownTypes{Bool: &wpb.BoolValue{Value: true}}},
822	{"StringValue", Unmarshaler{}, `{"str":"plush"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "plush"}}},
823	{"StringValue containing escaped character", Unmarshaler{}, `{"str":"a\/b"}`, &pb.KnownTypes{Str: &wpb.StringValue{Value: "a/b"}}},
824	{"StructValue containing StringValue's", Unmarshaler{}, `{"escaped": "a\/b", "unicode": "\u00004E16\u0000754C"}`,
825		&stpb.Struct{
826			Fields: map[string]*stpb.Value{
827				"escaped": {Kind: &stpb.Value_StringValue{"a/b"}},
828				"unicode": {Kind: &stpb.Value_StringValue{"\u00004E16\u0000754C"}},
829			},
830		}},
831	{"BytesValue", Unmarshaler{}, `{"bytes":"d293"}`, &pb.KnownTypes{Bytes: &wpb.BytesValue{Value: []byte("wow")}}},
832
833	// Ensure that `null` as a value ends up with a nil pointer instead of a [type]Value struct.
834	{"null DoubleValue", Unmarshaler{}, `{"dbl":null}`, &pb.KnownTypes{Dbl: nil}},
835	{"null FloatValue", Unmarshaler{}, `{"flt":null}`, &pb.KnownTypes{Flt: nil}},
836	{"null Int64Value", Unmarshaler{}, `{"i64":null}`, &pb.KnownTypes{I64: nil}},
837	{"null UInt64Value", Unmarshaler{}, `{"u64":null}`, &pb.KnownTypes{U64: nil}},
838	{"null Int32Value", Unmarshaler{}, `{"i32":null}`, &pb.KnownTypes{I32: nil}},
839	{"null UInt32Value", Unmarshaler{}, `{"u32":null}`, &pb.KnownTypes{U32: nil}},
840	{"null BoolValue", Unmarshaler{}, `{"bool":null}`, &pb.KnownTypes{Bool: nil}},
841	{"null StringValue", Unmarshaler{}, `{"str":null}`, &pb.KnownTypes{Str: nil}},
842	{"null BytesValue", Unmarshaler{}, `{"bytes":null}`, &pb.KnownTypes{Bytes: nil}},
843
844	{"required", Unmarshaler{}, `{"str":"hello"}`, &pb.MsgWithRequired{Str: proto.String("hello")}},
845	{"required bytes", Unmarshaler{}, `{"byts": []}`, &pb.MsgWithRequiredBytes{Byts: []byte{}}},
846}
847
848func TestUnmarshaling(t *testing.T) {
849	for _, tt := range unmarshalingTests {
850		// Make a new instance of the type of our expected object.
851		p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
852
853		err := tt.unmarshaler.Unmarshal(strings.NewReader(tt.json), p)
854		if err != nil {
855			t.Errorf("unmarshalling %s: %v", tt.desc, err)
856			continue
857		}
858
859		// For easier diffs, compare text strings of the protos.
860		exp := proto.MarshalTextString(tt.pb)
861		act := proto.MarshalTextString(p)
862		if string(exp) != string(act) {
863			t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
864		}
865	}
866}
867
868func TestUnmarshalNullArray(t *testing.T) {
869	var repeats pb.Repeats
870	if err := UnmarshalString(`{"rBool":null}`, &repeats); err != nil {
871		t.Fatal(err)
872	}
873	if !reflect.DeepEqual(repeats, pb.Repeats{}) {
874		t.Errorf("got non-nil fields in [%#v]", repeats)
875	}
876}
877
878func TestUnmarshalNullObject(t *testing.T) {
879	var maps pb.Maps
880	if err := UnmarshalString(`{"mInt64Str":null}`, &maps); err != nil {
881		t.Fatal(err)
882	}
883	if !reflect.DeepEqual(maps, pb.Maps{}) {
884		t.Errorf("got non-nil fields in [%#v]", maps)
885	}
886}
887
888func TestUnmarshalNext(t *testing.T) {
889	// We only need to check against a few, not all of them.
890	tests := unmarshalingTests[:5]
891
892	// Create a buffer with many concatenated JSON objects.
893	var b bytes.Buffer
894	for _, tt := range tests {
895		b.WriteString(tt.json)
896	}
897
898	dec := json.NewDecoder(&b)
899	for _, tt := range tests {
900		// Make a new instance of the type of our expected object.
901		p := reflect.New(reflect.TypeOf(tt.pb).Elem()).Interface().(proto.Message)
902
903		err := tt.unmarshaler.UnmarshalNext(dec, p)
904		if err != nil {
905			t.Errorf("%s: %v", tt.desc, err)
906			continue
907		}
908
909		// For easier diffs, compare text strings of the protos.
910		exp := proto.MarshalTextString(tt.pb)
911		act := proto.MarshalTextString(p)
912		if string(exp) != string(act) {
913			t.Errorf("%s: got [%s] want [%s]", tt.desc, act, exp)
914		}
915	}
916
917	p := &pb.Simple{}
918	err := new(Unmarshaler).UnmarshalNext(dec, p)
919	if err != io.EOF {
920		t.Errorf("eof: got %v, expected io.EOF", err)
921	}
922}
923
924var unmarshalingShouldError = []struct {
925	desc string
926	in   string
927	pb   proto.Message
928}{
929	{"a value", "666", new(pb.Simple)},
930	{"gibberish", "{adskja123;l23=-=", new(pb.Simple)},
931	{"unknown field", `{"unknown": "foo"}`, new(pb.Simple)},
932	{"unknown enum name", `{"hilarity":"DAVE"}`, new(proto3pb.Message)},
933	{"Duration containing invalid character", `{"dur": "3\U0073"}`, &pb.KnownTypes{}},
934	{"Timestamp containing invalid character", `{"ts": "2014-05-13T16:53:20\U005a"}`, &pb.KnownTypes{}},
935	{"StringValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &pb.KnownTypes{}},
936	{"StructValue containing invalid character", `{"str": "\U00004E16\U0000754C"}`, &stpb.Struct{}},
937	{"repeated proto3 enum with non array input", `{"rFunny":"PUNS"}`, &proto3pb.Message{RFunny: []proto3pb.Message_Humour{}}},
938}
939
940func TestUnmarshalingBadInput(t *testing.T) {
941	for _, tt := range unmarshalingShouldError {
942		err := UnmarshalString(tt.in, tt.pb)
943		if err == nil {
944			t.Errorf("an error was expected when parsing %q instead of an object", tt.desc)
945		}
946	}
947}
948
949type funcResolver func(turl string) (proto.Message, error)
950
951func (fn funcResolver) Resolve(turl string) (proto.Message, error) {
952	return fn(turl)
953}
954
955func TestAnyWithCustomResolver(t *testing.T) {
956	var resolvedTypeUrls []string
957	resolver := funcResolver(func(turl string) (proto.Message, error) {
958		resolvedTypeUrls = append(resolvedTypeUrls, turl)
959		return new(pb.Simple), nil
960	})
961	msg := &pb.Simple{
962		OBytes:  []byte{1, 2, 3, 4},
963		OBool:   proto.Bool(true),
964		OString: proto.String("foobar"),
965		OInt64:  proto.Int64(1020304),
966	}
967	msgBytes, err := proto.Marshal(msg)
968	if err != nil {
969		t.Errorf("an unexpected error occurred when marshaling message: %v", err)
970	}
971	// make an Any with a type URL that won't resolve w/out custom resolver
972	any := &anypb.Any{
973		TypeUrl: "https://foobar.com/some.random.MessageKind",
974		Value:   msgBytes,
975	}
976
977	m := Marshaler{AnyResolver: resolver}
978	js, err := m.MarshalToString(any)
979	if err != nil {
980		t.Errorf("an unexpected error occurred when marshaling any to JSON: %v", err)
981	}
982	if len(resolvedTypeUrls) != 1 {
983		t.Errorf("custom resolver was not invoked during marshaling")
984	} else if resolvedTypeUrls[0] != "https://foobar.com/some.random.MessageKind" {
985		t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[0], "https://foobar.com/some.random.MessageKind")
986	}
987	wanted := `{"@type":"https://foobar.com/some.random.MessageKind","oBool":true,"oInt64":"1020304","oString":"foobar","oBytes":"AQIDBA=="}`
988	if js != wanted {
989		t.Errorf("marshalling JSON produced incorrect output: got %s, wanted %s", js, wanted)
990	}
991
992	u := Unmarshaler{AnyResolver: resolver}
993	roundTrip := &anypb.Any{}
994	err = u.Unmarshal(bytes.NewReader([]byte(js)), roundTrip)
995	if err != nil {
996		t.Errorf("an unexpected error occurred when unmarshaling any from JSON: %v", err)
997	}
998	if len(resolvedTypeUrls) != 2 {
999		t.Errorf("custom resolver was not invoked during marshaling")
1000	} else if resolvedTypeUrls[1] != "https://foobar.com/some.random.MessageKind" {
1001		t.Errorf("custom resolver was invoked with wrong URL: got %q, wanted %q", resolvedTypeUrls[1], "https://foobar.com/some.random.MessageKind")
1002	}
1003	if !proto.Equal(any, roundTrip) {
1004		t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", roundTrip, any)
1005	}
1006}
1007
1008func TestUnmarshalJSONPBUnmarshaler(t *testing.T) {
1009	rawJson := `{ "foo": "bar", "baz": [0, 1, 2, 3] }`
1010	var msg dynamicMessage
1011	if err := Unmarshal(strings.NewReader(rawJson), &msg); err != nil {
1012		t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err)
1013	}
1014	if msg.RawJson != rawJson {
1015		t.Errorf("message contents not set correctly after unmarshalling JSON: got %s, wanted %s", msg.RawJson, rawJson)
1016	}
1017}
1018
1019func TestUnmarshalNullWithJSONPBUnmarshaler(t *testing.T) {
1020	rawJson := `{"stringField":null}`
1021	var ptrFieldMsg ptrFieldMessage
1022	if err := Unmarshal(strings.NewReader(rawJson), &ptrFieldMsg); err != nil {
1023		t.Errorf("unmarshal error: %v", err)
1024	}
1025
1026	want := ptrFieldMessage{StringField: &stringField{IsSet: true, StringValue: "null"}}
1027	if !proto.Equal(&ptrFieldMsg, &want) {
1028		t.Errorf("unmarshal result StringField: got %v, want %v", ptrFieldMsg, want)
1029	}
1030}
1031
1032func TestUnmarshalAnyJSONPBUnmarshaler(t *testing.T) {
1033	rawJson := `{ "@type": "blah.com/` + dynamicMessageName + `", "foo": "bar", "baz": [0, 1, 2, 3] }`
1034	var got anypb.Any
1035	if err := Unmarshal(strings.NewReader(rawJson), &got); err != nil {
1036		t.Errorf("an unexpected error occurred when parsing into JSONPBUnmarshaler: %v", err)
1037	}
1038
1039	dm := &dynamicMessage{RawJson: `{"baz":[0,1,2,3],"foo":"bar"}`}
1040	var want anypb.Any
1041	if b, err := proto.Marshal(dm); err != nil {
1042		t.Errorf("an unexpected error occurred when marshaling message: %v", err)
1043	} else {
1044		want.TypeUrl = "blah.com/" + dynamicMessageName
1045		want.Value = b
1046	}
1047
1048	if !proto.Equal(&got, &want) {
1049		t.Errorf("message contents not set correctly after unmarshalling JSON: got %v, wanted %v", got, want)
1050	}
1051}
1052
1053const (
1054	dynamicMessageName = "google.protobuf.jsonpb.testing.dynamicMessage"
1055)
1056
1057func init() {
1058	// we register the custom type below so that we can use it in Any types
1059	proto.RegisterType((*dynamicMessage)(nil), dynamicMessageName)
1060}
1061
1062type ptrFieldMessage struct {
1063	StringField *stringField `protobuf:"bytes,1,opt,name=stringField"`
1064}
1065
1066func (m *ptrFieldMessage) Reset() {
1067}
1068
1069func (m *ptrFieldMessage) String() string {
1070	return m.StringField.StringValue
1071}
1072
1073func (m *ptrFieldMessage) ProtoMessage() {
1074}
1075
1076type stringField struct {
1077	IsSet       bool   `protobuf:"varint,1,opt,name=isSet"`
1078	StringValue string `protobuf:"bytes,2,opt,name=stringValue"`
1079}
1080
1081func (s *stringField) Reset() {
1082}
1083
1084func (s *stringField) String() string {
1085	return s.StringValue
1086}
1087
1088func (s *stringField) ProtoMessage() {
1089}
1090
1091func (s *stringField) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
1092	s.IsSet = true
1093	s.StringValue = string(js)
1094	return nil
1095}
1096
1097// dynamicMessage implements protobuf.Message but is not a normal generated message type.
1098// It provides implementations of JSONPBMarshaler and JSONPBUnmarshaler for JSON support.
1099type dynamicMessage struct {
1100	RawJson string `protobuf:"bytes,1,opt,name=rawJson"`
1101
1102	// an unexported nested message is present just to ensure that it
1103	// won't result in a panic (see issue #509)
1104	Dummy *dynamicMessage `protobuf:"bytes,2,opt,name=dummy"`
1105}
1106
1107func (m *dynamicMessage) Reset() {
1108	m.RawJson = "{}"
1109}
1110
1111func (m *dynamicMessage) String() string {
1112	return m.RawJson
1113}
1114
1115func (m *dynamicMessage) ProtoMessage() {
1116}
1117
1118func (m *dynamicMessage) MarshalJSONPB(jm *Marshaler) ([]byte, error) {
1119	return []byte(m.RawJson), nil
1120}
1121
1122func (m *dynamicMessage) UnmarshalJSONPB(jum *Unmarshaler, js []byte) error {
1123	m.RawJson = string(js)
1124	return nil
1125}
1126
1127// Test unmarshaling message containing unset required fields should produce error.
1128func TestUnmarshalUnsetRequiredFields(t *testing.T) {
1129	tests := []struct {
1130		desc string
1131		pb   proto.Message
1132		json string
1133	}{
1134		{
1135			desc: "direct required field missing",
1136			pb:   &pb.MsgWithRequired{},
1137			json: `{}`,
1138		},
1139		{
1140			desc: "direct required field set to null",
1141			pb:   &pb.MsgWithRequired{},
1142			json: `{"str": null}`,
1143		},
1144		{
1145			desc: "indirect required field missing",
1146			pb:   &pb.MsgWithIndirectRequired{},
1147			json: `{"subm": {}}`,
1148		},
1149		{
1150			desc: "indirect required field set to null",
1151			pb:   &pb.MsgWithIndirectRequired{},
1152			json: `{"subm": {"str": null}}`,
1153		},
1154		{
1155			desc: "direct required bytes field missing",
1156			pb:   &pb.MsgWithRequiredBytes{},
1157			json: `{}`,
1158		},
1159		{
1160			desc: "direct required bytes field set to null",
1161			pb:   &pb.MsgWithRequiredBytes{},
1162			json: `{"byts": null}`,
1163		},
1164		{
1165			desc: "direct required wkt field missing",
1166			pb:   &pb.MsgWithRequiredWKT{},
1167			json: `{}`,
1168		},
1169		{
1170			desc: "direct required wkt field set to null",
1171			pb:   &pb.MsgWithRequiredWKT{},
1172			json: `{"str": null}`,
1173		},
1174		{
1175			desc: "any containing message with required field set to null",
1176			pb:   &pb.KnownTypes{},
1177			json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired", "str": null}}`,
1178		},
1179		{
1180			desc: "any containing message with missing required field",
1181			pb:   &pb.KnownTypes{},
1182			json: `{"an": {"@type": "example.com/jsonpb.MsgWithRequired"}}`,
1183		},
1184		{
1185			desc: "missing required in map value",
1186			pb:   &pb.MsgWithIndirectRequired{},
1187			json: `{"map_field": {"a": {}, "b": {"str": "hi"}}}`,
1188		},
1189		{
1190			desc: "required in map value set to null",
1191			pb:   &pb.MsgWithIndirectRequired{},
1192			json: `{"map_field": {"a": {"str": "hello"}, "b": {"str": null}}}`,
1193		},
1194		{
1195			desc: "missing required in slice item",
1196			pb:   &pb.MsgWithIndirectRequired{},
1197			json: `{"slice_field": [{}, {"str": "hi"}]}`,
1198		},
1199		{
1200			desc: "required in slice item set to null",
1201			pb:   &pb.MsgWithIndirectRequired{},
1202			json: `{"slice_field": [{"str": "hello"}, {"str": null}]}`,
1203		},
1204		{
1205			desc: "required inside oneof missing",
1206			pb:   &pb.MsgWithOneof{},
1207			json: `{"msgWithRequired": {}}`,
1208		},
1209		{
1210			desc: "required inside oneof set to null",
1211			pb:   &pb.MsgWithOneof{},
1212			json: `{"msgWithRequired": {"str": null}}`,
1213		},
1214		{
1215			desc: "required field in extension missing",
1216			pb:   &pb.Real{},
1217			json: `{"[jsonpb.extm]":{}}`,
1218		},
1219		{
1220			desc: "required field in extension set to null",
1221			pb:   &pb.Real{},
1222			json: `{"[jsonpb.extm]":{"str": null}}`,
1223		},
1224	}
1225
1226	for _, tc := range tests {
1227		if err := UnmarshalString(tc.json, tc.pb); err == nil {
1228			t.Errorf("%s: expecting error in unmarshaling with unset required fields %s", tc.desc, tc.json)
1229		}
1230	}
1231}
1232