mirror of https://github.com/jackc/pgx.git
decodeJSONB works for text and binary format
parent
c952d48a5c
commit
e96c105b55
13
values.go
13
values.go
|
@ -2087,13 +2087,16 @@ func decodeJSONB(vr *ValueReader, d interface{}) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes := vr.ReadBytes(vr.Len())
|
bytes := vr.ReadBytes(vr.Len())
|
||||||
if bytes[0] != 1 {
|
if vr.Type().FormatCode == BinaryFormatCode {
|
||||||
err := ProtocolError(fmt.Sprintf("Unknown jsonb format byte: %x", bytes[0]))
|
if bytes[0] != 1 {
|
||||||
vr.Fatal(err)
|
err := ProtocolError(fmt.Sprintf("Unknown jsonb format byte: %x", bytes[0]))
|
||||||
return err
|
vr.Fatal(err)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
bytes = bytes[1:]
|
||||||
}
|
}
|
||||||
|
|
||||||
err := json.Unmarshal(bytes[1:], d)
|
err := json.Unmarshal(bytes, d)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
vr.Fatal(err)
|
vr.Fatal(err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,67 +88,74 @@ func TestJsonAndJsonbTranscode(t *testing.T) {
|
||||||
if _, ok := conn.PgTypes[oid]; !ok {
|
if _, ok := conn.PgTypes[oid]; !ok {
|
||||||
return // No JSON/JSONB type -- must be running against old PostgreSQL
|
return // No JSON/JSONB type -- must be running against old PostgreSQL
|
||||||
}
|
}
|
||||||
typename := conn.PgTypes[oid].Name
|
|
||||||
|
|
||||||
testJsonString(t, conn, typename)
|
for _, format := range []int16{pgx.TextFormatCode, pgx.BinaryFormatCode} {
|
||||||
testJsonStringPointer(t, conn, typename)
|
pgtype := conn.PgTypes[oid]
|
||||||
testJsonSingleLevelStringMap(t, conn, typename)
|
pgtype.DefaultFormat = format
|
||||||
testJsonNestedMap(t, conn, typename)
|
conn.PgTypes[oid] = pgtype
|
||||||
testJsonStringArray(t, conn, typename)
|
|
||||||
testJsonInt64Array(t, conn, typename)
|
typename := conn.PgTypes[oid].Name
|
||||||
testJsonInt16ArrayFailureDueToOverflow(t, conn, typename)
|
|
||||||
testJsonStruct(t, conn, typename)
|
testJsonString(t, conn, typename, format)
|
||||||
|
testJsonStringPointer(t, conn, typename, format)
|
||||||
|
testJsonSingleLevelStringMap(t, conn, typename, format)
|
||||||
|
testJsonNestedMap(t, conn, typename, format)
|
||||||
|
testJsonStringArray(t, conn, typename, format)
|
||||||
|
testJsonInt64Array(t, conn, typename, format)
|
||||||
|
testJsonInt16ArrayFailureDueToOverflow(t, conn, typename, format)
|
||||||
|
testJsonStruct(t, conn, typename, format)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonString(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonString(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
input := `{"key": "value"}`
|
input := `{"key": "value"}`
|
||||||
expectedOutput := map[string]string{"key": "value"}
|
expectedOutput := map[string]string{"key": "value"}
|
||||||
var output map[string]string
|
var output map[string]string
|
||||||
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: QueryRow Scan failed: %v", typename, err)
|
t.Errorf("%s %d: QueryRow Scan failed: %v", typename, format, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(expectedOutput, output) {
|
if !reflect.DeepEqual(expectedOutput, output) {
|
||||||
t.Errorf("%s: Did not transcode map[string]string successfully: %v is not %v", typename, expectedOutput, output)
|
t.Errorf("%s %d: Did not transcode map[string]string successfully: %v is not %v", typename, format, expectedOutput, output)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonStringPointer(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonStringPointer(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
input := `{"key": "value"}`
|
input := `{"key": "value"}`
|
||||||
expectedOutput := map[string]string{"key": "value"}
|
expectedOutput := map[string]string{"key": "value"}
|
||||||
var output map[string]string
|
var output map[string]string
|
||||||
err := conn.QueryRow("select $1::"+typename, &input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, &input).Scan(&output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: QueryRow Scan failed: %v", typename, err)
|
t.Errorf("%s %d: QueryRow Scan failed: %v", typename, format, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(expectedOutput, output) {
|
if !reflect.DeepEqual(expectedOutput, output) {
|
||||||
t.Errorf("%s: Did not transcode map[string]string successfully: %v is not %v", typename, expectedOutput, output)
|
t.Errorf("%s %d: Did not transcode map[string]string successfully: %v is not %v", typename, format, expectedOutput, output)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonSingleLevelStringMap(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonSingleLevelStringMap(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
input := map[string]string{"key": "value"}
|
input := map[string]string{"key": "value"}
|
||||||
var output map[string]string
|
var output map[string]string
|
||||||
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: QueryRow Scan failed: %v", typename, err)
|
t.Errorf("%s %d: QueryRow Scan failed: %v", typename, format, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(input, output) {
|
if !reflect.DeepEqual(input, output) {
|
||||||
t.Errorf("%s: Did not transcode map[string]string successfully: %v is not %v", typename, input, output)
|
t.Errorf("%s %d: Did not transcode map[string]string successfully: %v is not %v", typename, format, input, output)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonNestedMap(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonNestedMap(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
input := map[string]interface{}{
|
input := map[string]interface{}{
|
||||||
"name": "Uncanny",
|
"name": "Uncanny",
|
||||||
"stats": map[string]interface{}{"hp": float64(107), "maxhp": float64(150)},
|
"stats": map[string]interface{}{"hp": float64(107), "maxhp": float64(150)},
|
||||||
|
@ -157,52 +164,52 @@ func testJsonNestedMap(t *testing.T, conn *pgx.Conn, typename string) {
|
||||||
var output map[string]interface{}
|
var output map[string]interface{}
|
||||||
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: QueryRow Scan failed: %v", typename, err)
|
t.Errorf("%s %d: QueryRow Scan failed: %v", typename, format, err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(input, output) {
|
if !reflect.DeepEqual(input, output) {
|
||||||
t.Errorf("%s: Did not transcode map[string]interface{} successfully: %v is not %v", typename, input, output)
|
t.Errorf("%s %d: Did not transcode map[string]interface{} successfully: %v is not %v", typename, format, input, output)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonStringArray(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonStringArray(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
input := []string{"foo", "bar", "baz"}
|
input := []string{"foo", "bar", "baz"}
|
||||||
var output []string
|
var output []string
|
||||||
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: QueryRow Scan failed: %v", typename, err)
|
t.Errorf("%s %d: QueryRow Scan failed: %v", typename, format, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(input, output) {
|
if !reflect.DeepEqual(input, output) {
|
||||||
t.Errorf("%s: Did not transcode []string successfully: %v is not %v", typename, input, output)
|
t.Errorf("%s %d: Did not transcode []string successfully: %v is not %v", typename, format, input, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonInt64Array(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonInt64Array(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
input := []int64{1, 2, 234432}
|
input := []int64{1, 2, 234432}
|
||||||
var output []int64
|
var output []int64
|
||||||
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: QueryRow Scan failed: %v", typename, err)
|
t.Errorf("%s %d: QueryRow Scan failed: %v", typename, format, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(input, output) {
|
if !reflect.DeepEqual(input, output) {
|
||||||
t.Errorf("%s: Did not transcode []int64 successfully: %v is not %v", typename, input, output)
|
t.Errorf("%s %d: Did not transcode []int64 successfully: %v is not %v", typename, format, input, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonInt16ArrayFailureDueToOverflow(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonInt16ArrayFailureDueToOverflow(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
input := []int{1, 2, 234432}
|
input := []int{1, 2, 234432}
|
||||||
var output []int16
|
var output []int16
|
||||||
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
||||||
if err == nil || err.Error() != "can't scan into dest[0]: json: cannot unmarshal number 234432 into Go value of type int16" {
|
if err == nil || err.Error() != "can't scan into dest[0]: json: cannot unmarshal number 234432 into Go value of type int16" {
|
||||||
t.Errorf("%s: Expected *json.UnmarkalTypeError, but got %v", typename, err)
|
t.Errorf("%s %d: Expected *json.UnmarkalTypeError, but got %v", typename, format, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func testJsonStruct(t *testing.T, conn *pgx.Conn, typename string) {
|
func testJsonStruct(t *testing.T, conn *pgx.Conn, typename string, format int16) {
|
||||||
type person struct {
|
type person struct {
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
Age int `json:"age"`
|
Age int `json:"age"`
|
||||||
|
@ -217,11 +224,11 @@ func testJsonStruct(t *testing.T, conn *pgx.Conn, typename string) {
|
||||||
|
|
||||||
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
err := conn.QueryRow("select $1::"+typename, input).Scan(&output)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Errorf("%s: QueryRow Scan failed: %v", typename, err)
|
t.Errorf("%s %d: QueryRow Scan failed: %v", typename, format, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !reflect.DeepEqual(input, output) {
|
if !reflect.DeepEqual(input, output) {
|
||||||
t.Errorf("%s: Did not transcode struct successfully: %v is not %v", typename, input, output)
|
t.Errorf("%s %d: Did not transcode struct successfully: %v is not %v", typename, format, input, output)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue