Skip to content

Commit

Permalink
feat(tljson): add JSONValue helper
Browse files Browse the repository at this point in the history
  • Loading branch information
tdakkota committed Dec 4, 2021
1 parent 89092b4 commit b277fac
Show file tree
Hide file tree
Showing 3 changed files with 170 additions and 0 deletions.
101 changes: 101 additions & 0 deletions telegram/tljson/convert.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
package tljson

import (
"github.com/go-faster/errors"
"github.com/go-faster/jx"

"github.com/gotd/td/tg"
)

// Decode decodes JSON and converts it to tg.JSONValueClass.
func Decode(d *jx.Decoder) (tg.JSONValueClass, error) {
switch tt := d.Next(); tt {
case jx.String:
s, err := d.Str()
if err != nil {
return nil, err
}
return &tg.JSONString{Value: s}, nil
case jx.Number:
f, err := d.Float64()
if err != nil {
return nil, err
}
return &tg.JSONNumber{Value: f}, nil
case jx.Null:
if err := d.Null(); err != nil {
return nil, err
}
return &tg.JSONNull{}, nil
case jx.Bool:
b, err := d.Bool()
if err != nil {
return nil, err
}
return &tg.JSONBool{Value: b}, nil
case jx.Array:
var r []tg.JSONValueClass
if err := d.Arr(func(d *jx.Decoder) error {
obj, err := Decode(d)
if err != nil {
return errors.Wrapf(err, "decode %d element", len(r))
}

r = append(r, obj)
return nil
}); err != nil {
return nil, err
}
return &tg.JSONArray{Value: r}, nil
case jx.Object:
var r []tg.JSONObjectValue
if err := d.Obj(func(d *jx.Decoder, key string) error {
obj, err := Decode(d)
if err != nil {
return errors.Wrapf(err, "decode %q", key)
}

r = append(r, tg.JSONObjectValue{
Key: key,
Value: obj,
})
return nil
}); err != nil {
return nil, err
}
return &tg.JSONObject{Value: r}, nil
default:
return nil, errors.Errorf("unexpected type %v", tt)
}
}

// Encode writes given value to Encoder.
func Encode(obj tg.JSONValueClass, e *jx.Encoder) {
switch obj := obj.(type) {
case *tg.JSONNull:
e.Null()
case *tg.JSONBool:
e.Bool(obj.Value)
case *tg.JSONNumber:
if v := int64(obj.Value); float64(v) == obj.Value {
e.Int64(v)
} else {
e.Float64(obj.Value)
}
case *tg.JSONString:
e.Str(obj.Value)
case *tg.JSONArray:
e.ArrStart()
for _, v := range obj.Value {
Encode(v, e)
}
e.ArrEnd()
case *tg.JSONObject:
e.ObjStart()
for _, pair := range obj.Value {
e.FieldStart(pair.Key)
Encode(pair.Value, e)
}
e.ObjEnd()
}
}
67 changes: 67 additions & 0 deletions telegram/tljson/convert_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
package tljson

import (
"testing"

"github.com/go-faster/jx"
"github.com/stretchr/testify/require"

"github.com/gotd/td/tg"
)

func TestDecodeEncodeDecode(t *testing.T) {
tests := []struct {
name string
input string
wantErr bool
expect tg.JSONValueClass
}{
{"Empty", "", true, nil},
{"InvalidNull", "nul", true, nil},
{"InvalidTrue", "tru", true, nil},
{"InvalidFalse", "falsy", true, nil},
{"InvalidInt", `[1a]"`, true, nil},
{"InvalidFloat", "1.", true, nil},
{"InvalidString", `"hello`, true, nil},
{"InvalidArray", "[1, 2, 3.]", true, nil},
{"InvalidObject", `{"abc":"def}`, true, nil},

{"Null", "null", false, nil},
{"True", "true", false, nil},
{"False", "false", false, nil},
{"Int", "10", false, nil},
{"Float", "1.1", false, nil},
{"String", `"hello"`, false, nil},
{"EmptyArray", "[]", false, nil},
{"Array", "[1, 2, 3]", false, nil},
{"EmptyObject", `{}`, false, nil},
{"Object", `{"abc":"def"}`, false, nil},
{"Tree", `{"a":1,"b":true,"c":null,"sub":{"abc":"def"}}`, false, nil},
}
for _, tt := range tests {
tt := tt

t.Run(tt.name, func(t *testing.T) {
a := require.New(t)

// Decode.
d := jx.DecodeStr(tt.input)
obj, err := Decode(d)
if tt.wantErr {
a.Error(err)
return
}
a.NoError(err)

// Encode.
e := jx.GetEncoder()
Encode(obj, e)

// Decode.
d.ResetBytes(e.Bytes())
obj2, err := Decode(d)
a.NoError(err)
a.Equal(obj, obj2)
})
}
}
2 changes: 2 additions & 0 deletions telegram/tljson/tljson.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// Package tljson contains some helpers to work with JSONValue class.
package tljson

0 comments on commit b277fac

Please sign in to comment.