ebuchman: added some demos on how to parse unknown types
This commit is contained in:
parent
acfbea6d49
commit
257f45b768
|
@ -0,0 +1,133 @@
|
|||
package rpcserver
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"testing"
|
||||
|
||||
"github.com/stretchr/testify/assert"
|
||||
"github.com/tendermint/go-wire/data"
|
||||
)
|
||||
|
||||
func TestParseJSONMap(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
input := []byte(`{"value":"1234","height":22}`)
|
||||
|
||||
// naive is float,string
|
||||
var p1 map[string]interface{}
|
||||
err := json.Unmarshal(input, &p1)
|
||||
if assert.Nil(err) {
|
||||
h, ok := p1["height"].(float64)
|
||||
if assert.True(ok, "%#v", p1["height"]) {
|
||||
assert.EqualValues(22, h)
|
||||
}
|
||||
v, ok := p1["value"].(string)
|
||||
if assert.True(ok, "%#v", p1["value"]) {
|
||||
assert.EqualValues("1234", v)
|
||||
}
|
||||
}
|
||||
|
||||
// preloading map with values doesn't help
|
||||
tmp := 0
|
||||
p2 := map[string]interface{}{
|
||||
"value": &data.Bytes{},
|
||||
"height": &tmp,
|
||||
}
|
||||
err = json.Unmarshal(input, &p2)
|
||||
if assert.Nil(err) {
|
||||
h, ok := p2["height"].(float64)
|
||||
if assert.True(ok, "%#v", p2["height"]) {
|
||||
assert.EqualValues(22, h)
|
||||
}
|
||||
v, ok := p2["value"].(string)
|
||||
if assert.True(ok, "%#v", p2["value"]) {
|
||||
assert.EqualValues("1234", v)
|
||||
}
|
||||
}
|
||||
|
||||
// preload here with *pointers* to the desired types
|
||||
// struct has unknown types, but hard-coded keys
|
||||
tmp = 0
|
||||
p3 := struct {
|
||||
Value interface{} `json:"value"`
|
||||
Height interface{} `json:"height"`
|
||||
}{
|
||||
Height: &tmp,
|
||||
Value: &data.Bytes{},
|
||||
}
|
||||
err = json.Unmarshal(input, &p3)
|
||||
if assert.Nil(err) {
|
||||
h, ok := p3.Height.(*int)
|
||||
if assert.True(ok, "%#v", p3.Height) {
|
||||
assert.Equal(22, *h)
|
||||
}
|
||||
v, ok := p3.Value.(*data.Bytes)
|
||||
if assert.True(ok, "%#v", p3.Value) {
|
||||
assert.EqualValues([]byte{0x12, 0x34}, *v)
|
||||
}
|
||||
}
|
||||
|
||||
// simplest solution, but hard-coded
|
||||
p4 := struct {
|
||||
Value data.Bytes `json:"value"`
|
||||
Height int `json:"height"`
|
||||
}{}
|
||||
err = json.Unmarshal(input, &p4)
|
||||
if assert.Nil(err) {
|
||||
assert.EqualValues(22, p4.Height)
|
||||
assert.EqualValues([]byte{0x12, 0x34}, p4.Value)
|
||||
}
|
||||
|
||||
// so, let's use this trick...
|
||||
// dynamic keys on map, and we can deserialize to the desired types
|
||||
var p5 map[string]*json.RawMessage
|
||||
err = json.Unmarshal(input, &p5)
|
||||
if assert.Nil(err) {
|
||||
var h int
|
||||
err = json.Unmarshal(*p5["height"], &h)
|
||||
if assert.Nil(err) {
|
||||
assert.Equal(22, h)
|
||||
}
|
||||
|
||||
var v data.Bytes
|
||||
err = json.Unmarshal(*p5["value"], &v)
|
||||
if assert.Nil(err) {
|
||||
assert.Equal(data.Bytes{0x12, 0x34}, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestParseJSONArray(t *testing.T) {
|
||||
assert := assert.New(t)
|
||||
|
||||
input := []byte(`["1234",22]`)
|
||||
|
||||
// naive is float,string
|
||||
var p1 []interface{}
|
||||
err := json.Unmarshal(input, &p1)
|
||||
if assert.Nil(err) {
|
||||
v, ok := p1[0].(string)
|
||||
if assert.True(ok, "%#v", p1[0]) {
|
||||
assert.EqualValues("1234", v)
|
||||
}
|
||||
h, ok := p1[1].(float64)
|
||||
if assert.True(ok, "%#v", p1[1]) {
|
||||
assert.EqualValues(22, h)
|
||||
}
|
||||
}
|
||||
|
||||
// preloading map with values helps here (unlike map - p2 above)
|
||||
tmp := 0
|
||||
p2 := []interface{}{&data.Bytes{}, &tmp}
|
||||
err = json.Unmarshal(input, &p2)
|
||||
if assert.Nil(err) {
|
||||
v, ok := p2[0].(*data.Bytes)
|
||||
if assert.True(ok, "%#v", p2[0]) {
|
||||
assert.EqualValues([]byte{0x12, 0x34}, *v)
|
||||
}
|
||||
h, ok := p2[1].(*int)
|
||||
if assert.True(ok, "%#v", p2[1]) {
|
||||
assert.EqualValues(22, *h)
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue