encoding/jsonpb: add support for unmarshaling Any
Also added json.Decoder.Clone API for unmarshaling Any to look
ahead remaining bytes for @type field.
Change-Id: I2f803743534dfb64f9092d716805b115faa5975a
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/170102
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/internal/encoding/json/decode.go b/internal/encoding/json/decode.go
index a9262b8..0ee6c85 100644
--- a/internal/encoding/json/decode.go
+++ b/internal/encoding/json/decode.go
@@ -25,7 +25,8 @@
// Decoder is a token-based JSON decoder.
type Decoder struct {
- // lastCall is last method called, eiterh readCall or peekCall.
+ // lastCall is last method called, either readCall or peekCall.
+ // Initial value is readCall.
lastCall call
// value contains the last read value.
@@ -88,7 +89,7 @@
case Bool, Number:
if !d.isValueNext() {
- return Value{}, d.newSyntaxError("unexpected value %v", value)
+ return Value{}, d.newSyntaxError("unexpected value %v", value.Raw())
}
case String:
@@ -97,7 +98,7 @@
}
// Check if this is for an object name.
if d.value.typ&(StartObject|comma) == 0 {
- return Value{}, d.newSyntaxError("unexpected value %q", value)
+ return Value{}, d.newSyntaxError("unexpected value %v", value.Raw())
}
d.in = d.in[n:]
d.consume(0)
@@ -109,7 +110,7 @@
case StartObject, StartArray:
if !d.isValueNext() {
- return Value{}, d.newSyntaxError("unexpected character %v", value)
+ return Value{}, d.newSyntaxError("unexpected character %v", value.Raw())
}
d.startStack = append(d.startStack, value.typ)
@@ -323,6 +324,14 @@
}
}
+// Clone returns a copy of the Decoder for use in reading ahead the next JSON
+// object, array or other values without affecting current Decoder.
+func (d *Decoder) Clone() *Decoder {
+ ret := *d
+ ret.startStack = append([]Type(nil), ret.startStack...)
+ return &ret
+}
+
// Value contains a JSON type and value parsed from calling Decoder.Read.
// For JSON boolean and string, it holds the converted value in boo and str
// fields respectively. For JSON number, input field holds a valid number which
@@ -377,6 +386,11 @@
return v.str, nil
}
+// Raw returns the read value in string.
+func (v Value) Raw() string {
+ return string(v.input)
+}
+
// Float returns the floating-point number if token is Number, else it will
// return an error.
//