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