package protojson
import (
)
func ( []byte, proto.Message) error {
return UnmarshalOptions{}.Unmarshal(, )
}
type UnmarshalOptions struct {
pragma.NoUnkeyedLiterals
AllowPartial bool
DiscardUnknown bool
Resolver interface {
protoregistry.MessageTypeResolver
protoregistry.ExtensionTypeResolver
}
}
func ( UnmarshalOptions) ( []byte, proto.Message) error {
return .unmarshal(, )
}
func ( UnmarshalOptions) ( []byte, proto.Message) error {
proto.Reset()
if .Resolver == nil {
.Resolver = protoregistry.GlobalTypes
}
:= decoder{json.NewDecoder(), }
if := .unmarshalMessage(.ProtoReflect(), false); != nil {
return
}
, := .Read()
if != nil {
return
}
if .Kind() != json.EOF {
return .unexpectedTokenError()
}
if .AllowPartial {
return nil
}
return proto.CheckInitialized()
}
type decoder struct {
*json.Decoder
opts UnmarshalOptions
}
func ( decoder) ( int, string, ...interface{}) error {
, := .Position()
:= fmt.Sprintf("(line %d:%d): ", , )
return errors.New(+, ...)
}
func ( decoder) ( json.Token) error {
return .syntaxError(.Pos(), "unexpected token %s", .RawString())
}
func ( decoder) ( int, string, ...interface{}) error {
, := .Position()
:= fmt.Sprintf("syntax error (line %d:%d): ", , )
return errors.New(+, ...)
}
func ( decoder) ( protoreflect.Message, bool) error {
if := wellKnownTypeUnmarshaler(.Descriptor().FullName()); != nil {
return (, )
}
, := .Read()
if != nil {
return
}
if .Kind() != json.ObjectOpen {
return .unexpectedTokenError()
}
:= .Descriptor()
if !flags.ProtoLegacy && messageset.IsMessageSet() {
return errors.New("no support for proto1 MessageSets")
}
var set.Ints
var set.Ints
:= .Fields()
for {
, := .Read()
if != nil {
return
}
switch .Kind() {
default:
return .unexpectedTokenError()
case json.ObjectClose:
return nil
case json.Name:
}
:= .Name()
if && == "@type" {
.Read()
continue
}
var protoreflect.FieldDescriptor
if strings.HasPrefix(, "[") && strings.HasSuffix(, "]") {
:= protoreflect.FullName([1 : len()-1])
, := .opts.Resolver.FindExtensionByName()
if != nil && != protoregistry.NotFound {
return .newError(.Pos(), "unable to resolve %s: %v", .RawString(), )
}
if != nil {
= .TypeDescriptor()
if !.ExtensionRanges().Has(.Number()) || .ContainingMessage().FullName() != .FullName() {
return .newError(.Pos(), "message %v cannot be extended by %v", .FullName(), .FullName())
}
}
} else {
= .ByJSONName()
if == nil {
= .ByTextName()
}
}
if flags.ProtoLegacy {
if != nil && .IsWeak() && .Message().IsPlaceholder() {
= nil
}
}
if == nil {
if .opts.DiscardUnknown {
if := .skipJSONValue(); != nil {
return
}
continue
}
return .newError(.Pos(), "unknown field %v", .RawString())
}
:= uint64(.Number())
if .Has() {
return .newError(.Pos(), "duplicate field %v", .RawString())
}
.Set()
if , := .Peek(); .Kind() == json.Null && !isKnownValue() && !isNullValue() {
.Read()
continue
}
switch {
case .IsList():
:= .Mutable().List()
if := .unmarshalList(, ); != nil {
return
}
case .IsMap():
:= .Mutable().Map()
if := .unmarshalMap(, ); != nil {
return
}
default:
if := .ContainingOneof(); != nil {
:= uint64(.Index())
if .Has() {
return .newError(.Pos(), "error parsing %s, oneof %v is already set", .RawString(), .FullName())
}
.Set()
}
if := .unmarshalSingular(, ); != nil {
return
}
}
}
}
func ( protoreflect.FieldDescriptor) bool {
:= .Message()
return != nil && .FullName() == genid.Value_message_fullname
}
func ( protoreflect.FieldDescriptor) bool {
:= .Enum()
return != nil && .FullName() == genid.NullValue_enum_fullname
}
func ( decoder) ( protoreflect.Message, protoreflect.FieldDescriptor) error {
var protoreflect.Value
var error
switch .Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind:
= .NewField()
= .unmarshalMessage(.Message(), false)
default:
, = .unmarshalScalar()
}
if != nil {
return
}
.Set(, )
return nil
}
func ( decoder) ( protoreflect.FieldDescriptor) (protoreflect.Value, error) {
const int = 32
const int = 64
, := .Read()
if != nil {
return protoreflect.Value{},
}
:= .Kind()
switch {
case protoreflect.BoolKind:
if .Kind() == json.Bool {
return protoreflect.ValueOfBool(.Bool()), nil
}
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
if , := unmarshalInt(, ); {
return , nil
}
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
if , := unmarshalInt(, ); {
return , nil
}
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
if , := unmarshalUint(, ); {
return , nil
}
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
if , := unmarshalUint(, ); {
return , nil
}
case protoreflect.FloatKind:
if , := unmarshalFloat(, ); {
return , nil
}
case protoreflect.DoubleKind:
if , := unmarshalFloat(, ); {
return , nil
}
case protoreflect.StringKind:
if .Kind() == json.String {
return protoreflect.ValueOfString(.ParsedString()), nil
}
case protoreflect.BytesKind:
if , := unmarshalBytes(); {
return , nil
}
case protoreflect.EnumKind:
if , := unmarshalEnum(, ); {
return , nil
}
default:
panic(fmt.Sprintf("unmarshalScalar: invalid scalar kind %v", ))
}
return protoreflect.Value{}, .newError(.Pos(), "invalid value for %v type: %v", , .RawString())
}
func ( json.Token, int) (protoreflect.Value, bool) {
switch .Kind() {
case json.Number:
return getInt(, )
case json.String:
:= strings.TrimSpace(.ParsedString())
if len() != len(.ParsedString()) {
return protoreflect.Value{}, false
}
:= json.NewDecoder([]byte())
, := .Read()
if != nil {
return protoreflect.Value{}, false
}
return getInt(, )
}
return protoreflect.Value{}, false
}
func ( json.Token, int) (protoreflect.Value, bool) {
, := .Int()
if ! {
return protoreflect.Value{}, false
}
if == 32 {
return protoreflect.ValueOfInt32(int32()), true
}
return protoreflect.ValueOfInt64(), true
}
func ( json.Token, int) (protoreflect.Value, bool) {
switch .Kind() {
case json.Number:
return getUint(, )
case json.String:
:= strings.TrimSpace(.ParsedString())
if len() != len(.ParsedString()) {
return protoreflect.Value{}, false
}
:= json.NewDecoder([]byte())
, := .Read()
if != nil {
return protoreflect.Value{}, false
}
return getUint(, )
}
return protoreflect.Value{}, false
}
func ( json.Token, int) (protoreflect.Value, bool) {
, := .Uint()
if ! {
return protoreflect.Value{}, false
}
if == 32 {
return protoreflect.ValueOfUint32(uint32()), true
}
return protoreflect.ValueOfUint64(), true
}
func ( json.Token, int) (protoreflect.Value, bool) {
switch .Kind() {
case json.Number:
return getFloat(, )
case json.String:
:= .ParsedString()
switch {
case "NaN":
if == 32 {
return protoreflect.ValueOfFloat32(float32(math.NaN())), true
}
return protoreflect.ValueOfFloat64(math.NaN()), true
case "Infinity":
if == 32 {
return protoreflect.ValueOfFloat32(float32(math.Inf(+1))), true
}
return protoreflect.ValueOfFloat64(math.Inf(+1)), true
case "-Infinity":
if == 32 {
return protoreflect.ValueOfFloat32(float32(math.Inf(-1))), true
}
return protoreflect.ValueOfFloat64(math.Inf(-1)), true
}
if len() != len(strings.TrimSpace()) {
return protoreflect.Value{}, false
}
:= json.NewDecoder([]byte())
, := .Read()
if != nil {
return protoreflect.Value{}, false
}
return getFloat(, )
}
return protoreflect.Value{}, false
}
func ( json.Token, int) (protoreflect.Value, bool) {
, := .Float()
if ! {
return protoreflect.Value{}, false
}
if == 32 {
return protoreflect.ValueOfFloat32(float32()), true
}
return protoreflect.ValueOfFloat64(), true
}
func ( json.Token) (protoreflect.Value, bool) {
if .Kind() != json.String {
return protoreflect.Value{}, false
}
:= .ParsedString()
:= base64.StdEncoding
if strings.ContainsAny(, "-_") {
= base64.URLEncoding
}
if len()%4 != 0 {
= .WithPadding(base64.NoPadding)
}
, := .DecodeString()
if != nil {
return protoreflect.Value{}, false
}
return protoreflect.ValueOfBytes(), true
}
func ( json.Token, protoreflect.FieldDescriptor) (protoreflect.Value, bool) {
switch .Kind() {
case json.String:
:= .ParsedString()
if := .Enum().Values().ByName(protoreflect.Name()); != nil {
return protoreflect.ValueOfEnum(.Number()), true
}
case json.Number:
if , := .Int(32); {
return protoreflect.ValueOfEnum(protoreflect.EnumNumber()), true
}
case json.Null:
if isNullValue() {
return protoreflect.ValueOfEnum(0), true
}
}
return protoreflect.Value{}, false
}
func ( decoder) ( protoreflect.List, protoreflect.FieldDescriptor) error {
, := .Read()
if != nil {
return
}
if .Kind() != json.ArrayOpen {
return .unexpectedTokenError()
}
switch .Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind:
for {
, := .Peek()
if != nil {
return
}
if .Kind() == json.ArrayClose {
.Read()
return nil
}
:= .NewElement()
if := .unmarshalMessage(.Message(), false); != nil {
return
}
.Append()
}
default:
for {
, := .Peek()
if != nil {
return
}
if .Kind() == json.ArrayClose {
.Read()
return nil
}
, := .unmarshalScalar()
if != nil {
return
}
.Append()
}
}
return nil
}
func ( decoder) ( protoreflect.Map, protoreflect.FieldDescriptor) error {
, := .Read()
if != nil {
return
}
if .Kind() != json.ObjectOpen {
return .unexpectedTokenError()
}
var func() (protoreflect.Value, error)
switch .MapValue().Kind() {
case protoreflect.MessageKind, protoreflect.GroupKind:
= func() (protoreflect.Value, error) {
:= .NewValue()
if := .unmarshalMessage(.Message(), false); != nil {
return protoreflect.Value{},
}
return , nil
}
default:
= func() (protoreflect.Value, error) {
return .unmarshalScalar(.MapValue())
}
}
:
for {
, := .Read()
if != nil {
return
}
switch .Kind() {
default:
return .unexpectedTokenError()
case json.ObjectClose:
break
case json.Name:
}
, := .unmarshalMapKey(, .MapKey())
if != nil {
return
}
if .Has() {
return .newError(.Pos(), "duplicate map key %v", .RawString())
}
, := ()
if != nil {
return
}
.Set(, )
}
return nil
}
func ( decoder) ( json.Token, protoreflect.FieldDescriptor) (protoreflect.MapKey, error) {
const = 32
const = 64
const = 10
:= .Name()
:= .Kind()
switch {
case protoreflect.StringKind:
return protoreflect.ValueOfString().MapKey(), nil
case protoreflect.BoolKind:
switch {
case "true":
return protoreflect.ValueOfBool(true).MapKey(), nil
case "false":
return protoreflect.ValueOfBool(false).MapKey(), nil
}
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
if , := strconv.ParseInt(, , ); == nil {
return protoreflect.ValueOfInt32(int32()).MapKey(), nil
}
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
if , := strconv.ParseInt(, , ); == nil {
return protoreflect.ValueOfInt64(int64()).MapKey(), nil
}
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
if , := strconv.ParseUint(, , ); == nil {
return protoreflect.ValueOfUint32(uint32()).MapKey(), nil
}
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
if , := strconv.ParseUint(, , ); == nil {
return protoreflect.ValueOfUint64(uint64()).MapKey(), nil
}
default:
panic(fmt.Sprintf("invalid kind for map key: %v", ))
}
return protoreflect.MapKey{}, .newError(.Pos(), "invalid value for %v key: %s", , .RawString())
}