package jsonpb
import (
protoV2
)
const wrapJSONUnmarshalV2 = false
func ( *json.Decoder, proto.Message) error {
return new(Unmarshaler).UnmarshalNext(, )
}
func ( io.Reader, proto.Message) error {
return new(Unmarshaler).Unmarshal(, )
}
func ( string, proto.Message) error {
return new(Unmarshaler).Unmarshal(strings.NewReader(), )
}
type Unmarshaler struct {
AllowUnknownFields bool
AnyResolver AnyResolver
}
type JSONPBUnmarshaler interface {
UnmarshalJSONPB(*Unmarshaler, []byte) error
}
func ( *Unmarshaler) ( io.Reader, proto.Message) error {
return .UnmarshalNext(json.NewDecoder(), )
}
func ( *Unmarshaler) ( *json.Decoder, proto.Message) error {
if == nil {
return errors.New("invalid nil message")
}
:= json.RawMessage{}
if := .Decode(&); != nil {
return
}
if , := .(JSONPBUnmarshaler); {
return .UnmarshalJSONPB(, )
}
:= proto.MessageReflect()
if string() == "null" && .Descriptor().FullName() != "google.protobuf.Value" {
return nil
}
if wrapJSONUnmarshalV2 {
:= true
.Range(func(protoreflect.FieldDescriptor, protoreflect.Value) bool {
= false
return false
})
if ! {
= .New()
:= proto.MessageReflect()
defer .Range(func( protoreflect.FieldDescriptor, protoreflect.Value) bool {
.Set(, )
return true
})
}
:= protojson.UnmarshalOptions{
DiscardUnknown: .AllowUnknownFields,
}
if .AnyResolver != nil {
.Resolver = anyResolver{.AnyResolver}
}
return .Unmarshal(, .Interface())
} else {
if := .unmarshalMessage(, ); != nil {
return
}
return protoV2.CheckInitialized(.Interface())
}
}
func ( *Unmarshaler) ( protoreflect.Message, []byte) error {
:= .Descriptor()
:= .Fields()
if , := proto.MessageV1(.Interface()).(JSONPBUnmarshaler); {
return .UnmarshalJSONPB(, )
}
if string() == "null" && .FullName() != "google.protobuf.Value" {
return nil
}
switch wellKnownType(.FullName()) {
case "Any":
var map[string]json.RawMessage
if := json.Unmarshal(, &); != nil {
return
}
, := ["@type"]
if ! {
return errors.New("Any JSON doesn't have '@type'")
}
, := unquoteString(string())
if != nil {
return fmt.Errorf("can't unmarshal Any's '@type': %q", )
}
.Set(.ByNumber(1), protoreflect.ValueOfString())
var protoreflect.Message
if .AnyResolver != nil {
, := .AnyResolver.Resolve()
if != nil {
return
}
= proto.MessageReflect()
} else {
, := protoregistry.GlobalTypes.FindMessageByURL()
if != nil {
if == protoregistry.NotFound {
return fmt.Errorf("could not resolve Any message type: %v", )
}
return
}
= .New()
}
if wellKnownType(.Descriptor().FullName()) != "" {
, := ["value"]
if ! {
return errors.New("Any JSON doesn't have 'value'")
}
if := .(, ); != nil {
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", , )
}
} else {
delete(, "@type")
, := json.Marshal()
if != nil {
return fmt.Errorf("can't generate JSON for Any's nested proto to be unmarshaled: %v", )
}
if = .(, ); != nil {
return fmt.Errorf("can't unmarshal Any nested proto %v: %v", , )
}
}
, := protoV2.Marshal(.Interface())
if != nil {
return fmt.Errorf("can't marshal proto %v into Any.Value: %v", , )
}
.Set(.ByNumber(2), protoreflect.ValueOfBytes())
return nil
case "BoolValue", "BytesValue", "StringValue",
"Int32Value", "UInt32Value", "FloatValue",
"Int64Value", "UInt64Value", "DoubleValue":
:= .ByNumber(1)
, := .unmarshalValue(.NewField(), , )
if != nil {
return
}
.Set(, )
return nil
case "Duration":
, := unquoteString(string())
if != nil {
return
}
, := time.ParseDuration()
if != nil {
return fmt.Errorf("bad Duration: %v", )
}
:= .Nanoseconds() / 1e9
:= .Nanoseconds() % 1e9
.Set(.ByNumber(1), protoreflect.ValueOfInt64(int64()))
.Set(.ByNumber(2), protoreflect.ValueOfInt32(int32()))
return nil
case "Timestamp":
, := unquoteString(string())
if != nil {
return
}
, := time.Parse(time.RFC3339Nano, )
if != nil {
return fmt.Errorf("bad Timestamp: %v", )
}
:= .Unix()
:= .Nanosecond()
.Set(.ByNumber(1), protoreflect.ValueOfInt64(int64()))
.Set(.ByNumber(2), protoreflect.ValueOfInt32(int32()))
return nil
case "Value":
switch {
case string() == "null":
.Set(.ByNumber(1), protoreflect.ValueOfEnum(0))
case string() == "true":
.Set(.ByNumber(4), protoreflect.ValueOfBool(true))
case string() == "false":
.Set(.ByNumber(4), protoreflect.ValueOfBool(false))
case hasPrefixAndSuffix('"', , '"'):
, := unquoteString(string())
if != nil {
return fmt.Errorf("unrecognized type for Value %q", )
}
.Set(.ByNumber(3), protoreflect.ValueOfString())
case hasPrefixAndSuffix('[', , ']'):
:= .Mutable(.ByNumber(6))
return .(.Message(), )
case hasPrefixAndSuffix('{', , '}'):
:= .Mutable(.ByNumber(5))
return .(.Message(), )
default:
, := strconv.ParseFloat(string(), 0)
if != nil {
return fmt.Errorf("unrecognized type for Value %q", )
}
.Set(.ByNumber(2), protoreflect.ValueOfFloat64())
}
return nil
case "ListValue":
var []json.RawMessage
if := json.Unmarshal(, &); != nil {
return fmt.Errorf("bad ListValue: %v", )
}
:= .Mutable(.ByNumber(1)).List()
for , := range {
:= .NewElement()
if := .(.Message(), ); != nil {
return
}
.Append()
}
return nil
case "Struct":
var map[string]json.RawMessage
if := json.Unmarshal(, &); != nil {
return fmt.Errorf("bad StructValue: %v", )
}
:= .Mutable(.ByNumber(1)).Map()
for , := range {
:= protoreflect.ValueOf().MapKey()
:= .NewValue()
if := .(.Message(), ); != nil {
return fmt.Errorf("bad value in StructValue for key %q: %v", , )
}
.Set(, )
}
return nil
}
var map[string]json.RawMessage
if := json.Unmarshal(, &); != nil {
return
}
for := 0; < .Len(); ++ {
:= .Get()
if .IsWeak() && .Message().IsPlaceholder() {
continue
}
var json.RawMessage
:= string(.Name())
if .Kind() == protoreflect.GroupKind {
= string(.Message().Name())
}
if , := []; {
delete(, )
=
}
= string(.JSONName())
if , := []; {
delete(, )
=
}
:= .NewField()
if == nil || (string() == "null" && !isSingularWellKnownValue() && !isSingularJSONPBUnmarshaler(, )) {
continue
}
, := .unmarshalValue(, , )
if != nil {
return
}
.Set(, )
}
for , := range {
if !strings.HasPrefix(, "[") || !strings.HasSuffix(, "]") {
continue
}
:= protoreflect.FullName([len("[") : len()-len("]")])
, := protoregistry.GlobalTypes.FindExtensionByName()
if == nil && isMessageSet() {
, _ = protoregistry.GlobalTypes.FindExtensionByName(.Append("message_set_extension"))
}
if == nil {
continue
}
delete(, )
:= .TypeDescriptor()
if .ContainingMessage().FullName() != .Descriptor().FullName() {
return fmt.Errorf("extension field %q does not extend message %q", , .Descriptor().FullName())
}
:= .NewField()
if == nil || (string() == "null" && !isSingularWellKnownValue() && !isSingularJSONPBUnmarshaler(, )) {
continue
}
, := .unmarshalValue(, , )
if != nil {
return
}
.Set(, )
}
if !.AllowUnknownFields && len() > 0 {
for := range {
return fmt.Errorf("unknown field %q in %v", , .FullName())
}
}
return nil
}
func ( protoreflect.FieldDescriptor) bool {
if := .Message(); != nil {
return .FullName() == "google.protobuf.Value" && .Cardinality() != protoreflect.Repeated
}
return false
}
func ( protoreflect.Value, protoreflect.FieldDescriptor) bool {
if .Message() != nil && .Cardinality() != protoreflect.Repeated {
, := proto.MessageV1(.Interface()).(JSONPBUnmarshaler)
return
}
return false
}
func ( *Unmarshaler) ( protoreflect.Value, []byte, protoreflect.FieldDescriptor) (protoreflect.Value, error) {
switch {
case .IsList():
var []json.RawMessage
if := json.Unmarshal(, &); != nil {
return ,
}
:= .List()
for , := range {
, := .unmarshalSingularValue(.NewElement(), , )
if != nil {
return ,
}
.Append()
}
return , nil
case .IsMap():
var map[string]json.RawMessage
if := json.Unmarshal(, &); != nil {
return ,
}
:= .MapKey()
:= .MapValue()
:= .Map()
for , := range {
var protoreflect.MapKey
if .Kind() == protoreflect.StringKind {
= protoreflect.ValueOf().MapKey()
} else {
, := .unmarshalSingularValue(.Default(), []byte(), )
if != nil {
return ,
}
= .MapKey()
}
, := .unmarshalSingularValue(.NewValue(), , )
if != nil {
return ,
}
.Set(, )
}
return , nil
default:
return .unmarshalSingularValue(, , )
}
}
var nonFinite = map[string]float64{
`"NaN"`: math.NaN(),
`"Infinity"`: math.Inf(+1),
`"-Infinity"`: math.Inf(-1),
}
func ( *Unmarshaler) ( protoreflect.Value, []byte, protoreflect.FieldDescriptor) (protoreflect.Value, error) {
switch .Kind() {
case protoreflect.BoolKind:
return unmarshalValue(, new(bool))
case protoreflect.Int32Kind, protoreflect.Sint32Kind, protoreflect.Sfixed32Kind:
return unmarshalValue(trimQuote(), new(int32))
case protoreflect.Int64Kind, protoreflect.Sint64Kind, protoreflect.Sfixed64Kind:
return unmarshalValue(trimQuote(), new(int64))
case protoreflect.Uint32Kind, protoreflect.Fixed32Kind:
return unmarshalValue(trimQuote(), new(uint32))
case protoreflect.Uint64Kind, protoreflect.Fixed64Kind:
return unmarshalValue(trimQuote(), new(uint64))
case protoreflect.FloatKind:
if , := nonFinite[string()]; {
return protoreflect.ValueOfFloat32(float32()), nil
}
return unmarshalValue(trimQuote(), new(float32))
case protoreflect.DoubleKind:
if , := nonFinite[string()]; {
return protoreflect.ValueOfFloat64(float64()), nil
}
return unmarshalValue(trimQuote(), new(float64))
case protoreflect.StringKind:
return unmarshalValue(, new(string))
case protoreflect.BytesKind:
return unmarshalValue(, new([]byte))
case protoreflect.EnumKind:
if hasPrefixAndSuffix('"', , '"') {
:= .Enum().Values().ByName(protoreflect.Name(trimQuote()))
if == nil {
return , fmt.Errorf("unknown value %q for enum %s", , .Enum().FullName())
}
return protoreflect.ValueOfEnum(.Number()), nil
}
return unmarshalValue(, new(protoreflect.EnumNumber))
case protoreflect.MessageKind, protoreflect.GroupKind:
:= .unmarshalMessage(.Message(), )
return ,
default:
panic(fmt.Sprintf("invalid kind %v", .Kind()))
}
}
func ( []byte, interface{}) (protoreflect.Value, error) {
:= json.Unmarshal(, )
return protoreflect.ValueOf(reflect.ValueOf().Elem().Interface()),
}
func ( string) ( string, error) {
= json.Unmarshal([]byte(), &)
return ,
}
func ( byte, []byte, byte) bool {
if len() >= 2 && [0] == && [len()-1] == {
return true
}
return false
}
func ( []byte) []byte {
if len() >= 2 && [0] == '"' && [len()-1] == '"' {
= [1 : len()-1]
}
return
}