x模块

json2

标准库中的json模块是基于CJSON实现的

json2则是纯V实现,目前还处在x实验性模块中,稳定后估计会替换掉标准库中的json模块

类型

  1. //Any是联合类型,表示json任意类型的节点
  2. pub type Any = string | int | i64 | f32 | f64 | any_int | any_float | bool | Null | []Any | map[string]Any
  3. //联合类型转换成具体类型的方法,主要用于实现from_json方法
  4. pub fn (f Any) as_map() map[string]Any //转字典
  5. pub fn (f Any) arr() []Any //转数组
  6. pub fn (f Any) str() string //转string
  7. pub fn (f Any) int() int //转int
  8. pub fn (f Any) i64() i64 //转i64
  9. pub fn (f Any) f32() f32 //转f32
  10. pub fn (f Any) f64() f64 //转f64
  11. pub fn (f Any) bool() bool //转bool

接口

  1. //JSON序列化接口,要进行JSON序列化的类型需要实现
  2. pub interface Serializable {
  3. from_json(f Any) //decode中使用
  4. to_json() string //encode中使用
  5. }

编码

  1. //泛型版本的编码函数,将类型为T的变量编码为json字符串
  2. pub fn encode<T>(typ T) string //类型需要实现序列化接口的to_json函数

解码

  1. //泛型版本的解码函数
  2. pub fn decode<T>(src string) ?T //返回类型为T的变量,类型需要实现序列化接口的from_json函数
  3. //解码函数,会自动转换节点的值为对应类型
  4. pub fn raw_decode(src string) ?Any //仅仅返回Any类型
  5. //快速解码函数,忽略类型转换,节点的值都是字符串
  6. pub fn fast_raw_decode(src string) ?Any

编码示例:

  1. import x.json2
  2. enum JobTitle {
  3. manager
  4. executive
  5. worker
  6. }
  7. struct Employee {
  8. mut:
  9. name string
  10. age int
  11. salary f32
  12. title JobTitle
  13. }
  14. // 实现JSON序列化接口,给encode使用
  15. pub fn (e Employee) to_json() string {
  16. mut mp := map[string]json2.Any{}
  17. mp['name'] = e.name
  18. mp['age'] = e.age
  19. mp['salary'] = e.salary
  20. mp['title'] = int(e.title)
  21. return mp.str()
  22. }
  23. // 实现JSON序列化接口,给decode使用
  24. pub fn (mut e Employee) from_json(f json2.Any) {
  25. mp := f.as_map()
  26. e.name = mp['name'].str()
  27. e.age = mp['age'].int()
  28. e.salary = mp['salary'].f32()
  29. e.title = mp['title'].int()
  30. }
  31. fn main() {
  32. x := Employee{'Peter', 28, 95000.5, .worker}
  33. s := json2.encode<Employee>(x)
  34. println(s)
  35. // generic decode
  36. gy := json2.decode<Employee>(s) or {
  37. panic(err)
  38. }
  39. println('Employee y: $gy')
  40. // raw_decode
  41. y := json2.raw_decode(s) or {
  42. panic(err)
  43. }
  44. println('Employee y: $y')
  45. }

websocket

客户端

  1. //创建websocket客户端
  2. pub fn new_client(address string) ?&Client
  1. //返回客户端对象
  2. pub struct Client {
  3. is_server bool
  4. mut:
  5. ssl_conn &openssl.SSLConn
  6. flags []Flag
  7. fragments []Fragment
  8. logger &log.Log
  9. message_callbacks []MessageEventHandler
  10. error_callbacks []ErrorEventHandler
  11. open_callbacks []OpenEventHandler
  12. close_callbacks []CloseEventHandler
  13. pub:
  14. is_ssl bool
  15. uri Uri
  16. id string
  17. pub mut:
  18. conn net.TcpConn
  19. nonce_size int = 16 // you can try 18 too
  20. panic_on_callback bool
  21. state State
  22. resource_name string
  23. last_pong_ut u64
  24. }
  1. //定义4个回调函数
  2. ws.on_open(fn (mut ws websocket.Client) ? //连接回调
  3. ws.on_error(fn (mut ws websocket.Client, err string) ? //报错回调
  4. ws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? //接收消息回调
  5. ws.on_close(fn (mut ws websocket.Client, code int, reason string) ? //关闭连接回调
  1. //跟服务端建立连接
  2. pub fn (mut ws Client) connect() ?
  1. //监听服务端发送的消息
  2. pub fn (mut ws Client) listen() ?
  1. //实现io模块的读写接口,读写消息
  2. pub fn (mut ws Client) write(bytes []byte, code OPCode) ?
  3. pub fn (mut ws Client) write_str(str string) ?

服务端

  1. //创建websocket服务端
  2. pub fn new_server(port int, route string) &Server
  1. //返回服务端对象
  2. pub struct Server {
  3. mut:
  4. clients map[string]&ServerClient
  5. logger &log.Log
  6. ls net.TcpListener
  7. accept_client_callbacks []AcceptClientFn
  8. message_callbacks []MessageEventHandler
  9. close_callbacks []CloseEventHandler
  10. pub:
  11. port int
  12. is_ssl bool
  13. pub mut:
  14. ping_interval int = 30 // in seconds
  15. state State
  16. }
  17. //
  18. struct ServerClient {
  19. pub:
  20. resource_name string
  21. client_key string
  22. pub mut:
  23. server &Server
  24. client &Client
  25. }
  1. //创建3个回调函数
  2. s.on_connect(fn (mut s websocket.ServerClient) ?bool //连接回调
  3. s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? //消息接收回调
  4. s.on_close(fn (mut ws websocket.Client, code int, reason string) ? //关闭连接回调
  1. //开始启动监听
  2. pub fn (mut s Server) listen() ?

演示实例代码

  1. module main
  2. import x.websocket
  3. import time
  4. fn main() {
  5. go start_server()
  6. time.sleep(100*time.millisecond)
  7. ws_client('ws://localhost:30000') ?
  8. }
  9. fn start_server() ? {
  10. mut s := websocket.new_server(30000, '')
  11. s.ping_interval = 100
  12. s.on_connect(fn (mut s websocket.ServerClient) ?bool {
  13. // Here you can look att the client info and accept or not accept
  14. // just returning a true/false
  15. if s.resource_name != '/' {
  16. panic('unexpected resource name in test')
  17. return false
  18. }
  19. return true
  20. }) ?
  21. s.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
  22. ws.write(msg.payload, msg.opcode) or {
  23. panic(err)
  24. }
  25. })
  26. s.on_close(fn (mut ws websocket.Client, code int, reason string) ? {
  27. println('client ($ws.id) closed connection')
  28. })
  29. s.listen() or {
  30. println('error on server listen: $err')
  31. }
  32. }
  33. fn ws_client(uri string) ? {
  34. eprintln('connecting to $uri ...')
  35. mut ws := websocket.new_client(uri) ?
  36. ws.on_open(fn (mut ws websocket.Client) ? {
  37. println('open!')
  38. ws.pong()
  39. })
  40. ws.on_error(fn (mut ws websocket.Client, err string) ? {
  41. println('error: $err')
  42. // this can be thrown by internet connection problems
  43. })
  44. ws.on_close(fn (mut ws websocket.Client, code int, reason string) ? {
  45. println('closed')
  46. })
  47. ws.on_message(fn (mut ws websocket.Client, msg &websocket.Message) ? {
  48. println('client got type: $msg.opcode payload:\n$msg.payload')
  49. if msg.opcode == .text_frame {
  50. smessage := msg.payload.bytestr()
  51. println('Message: $smessage')
  52. } else {
  53. println('Binary message: $msg')
  54. }
  55. })
  56. ws.connect() or {
  57. panic('fail to connect')
  58. }
  59. go ws.listen()
  60. text := ['a'].repeat(2)
  61. for msg in text {
  62. ws.write(msg.bytes(), .text_frame) or {
  63. panic('fail to write to websocket')
  64. }
  65. // wait to give time to recieve response before send a new one
  66. time.sleep(100*time.millisecond)
  67. }
  68. // wait to give time to recieve response before asserts
  69. time.sleep(500*time.millisecond)
  70. }