Bỏ qua

Gửi và nhận JSON

Trong hướng dẫn này, chúng tôi giải thích cách bạn có thể gửi và nhận các tin nhắn JSON.

TCP và WebSocket

Khi làm việc với JSON, bạn có thể sử dụng kết nối TCP hoặc kết nối WebSocket.

Gửi JSON

Nếu bạn chọn sử dụng JSON trong tích hợp của mình, bạn sẽ phải gửi các chuỗi chứa JSON hợp lệ đến backend của cTrader. Các đối tượng JSON được truyền dưới dạng các chuỗi này phải chứa các khóa sau.

Khóa Kiểu dữ liệu giá trị Định nghĩa
"clientMsgId" chuỗi ID duy nhất của một tin nhắn. ID này phải được tạo và gán từ phía client.
"payloadType" integer Số nguyên đại diện cho tin nhắn. Danh sách đầy đủ các loại payload hợp lệ được bao gồm trong ProtoOAPayloadType.
"payload" Đối tượng JSON Một đối tượng JSON lồng nhau chứa nội dung thực tế của tin nhắn.

Một ví dụ về chuỗi hợp lệ (đại diện cho tin nhắn ProtoOAApplicationAuthReq) có thể được tìm thấy bên dưới.

"{"clientMsgId": "cm_id_2", "payloadType": 2100, "payload": {"clientId": "34Rsd_T098asHkl","clientSecret": "validClientSecret"}}"

Để gửi các chuỗi JSON chính xác, bạn sẽ cần tạo một cơ chế tuần tự hóa tùy chỉnh trong ngôn ngữ lập trình bạn chọn.

Trong các ví dụ bên dưới, chúng tôi định nghĩa một số cách tiếp cận để xử lý tuần tự hóa. Bạn có thể (và nên) triển khai cách của riêng mình tùy thuộc vào ngôn ngữ lập trình và mẫu thiết kế bạn ưa thích.

Bên dưới, chúng tôi định nghĩa hai lớp cơ sở và sau đó tạo một biểu diễn tùy chỉnh của tin nhắn ProtoOAApplicationAuthReq.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public abstract class OpenAPIMessageBase
{
    public string ClientMsgId { get; set; }
    public abstract int PayloadType { get; }
}

public abstract class OpenAPIMessagePayloadBase { }

public class ApplicationAuthReq : OpenAPIMessageBase
{
    public ApplicationAuthReq() { }
    public ApplicationAuthReq(string clientId, string clientSecret)
    {
        this.Payload = new ApplicationAuthReqPayload(clientId, clientSecret);
        this.ClientMsgId = Guid.NewGuid().ToString();
    }

    public override int PayloadType => 2100;
    public ApplicationAuthReqPayload? Payload { get; set; }

}

public class ApplicationAuthReqPayload : OpenAPIMessagePayloadBase
{
    public ApplicationAuthReqPayload() { }
    public ApplicationAuthReqPayload(string clientId, string clientSecret)
    {
        this.ClientId = clientId;
        this.ClientSecret = clientSecret;
    }
    public string ClientId { get; set; } = string.Empty;
    public string ClientSecret { get; set; } = string.Empty;
}

Chúng tôi tạo một lớp cơ sở cho tất cả các tin nhắn Open API và, với mục đích minh họa, định nghĩa lớp cho ProtoOAApplicationAuthReq.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
import uuid
import json

class OpenAPIMessage:

def payloadType(self):
    pass

def payload(self):
    pass

def clientMsgId(self):
    pass

def asJsonString(self):
    pass


class ApplicationAuthReq(OpenAPIMessage):

def __init__(self, clientId, clientSecret, clientMsgId = str(uuid.uuid4())):
    self.clientId = clientId
    self.clientSecret = client_secret
    self.payloadType = 2100
    self.clientMsgId = clientMsgId
    self.payload = {"clientId": self.clientId, "clientSecret": self.clientSecret}



def asJsonString(self):
    return json.dumps({"clientMsgId": self.clientMsgId, "payloadType": self.payloadType, "payload": self.payload})

Sau khi triển khai logic cần thiết, bạn sẽ có thể gửi các tin nhắn mới đến backend của cTrader bằng cách tạo các phiên bản mới của các lớp đại diện cho các tin nhắn này và sau đó chuyển chúng đến client TCP hoặc WebSocket mà bạn ưa thích.

Nhận JSON

Để nhận và xử lý các tin nhắn JSON, bạn phải triển khai một phương pháp để giải tuần tự hóa một chuỗi JSON thành một biểu diễn của tin nhắn Open API.

Để triển khai phương pháp này, bạn có thể thấy hữu ích khi khởi tạo một bản đồ (hoặc từ điển) nơi các loại payload có thể là các khóa với tên của các lớp đại diện cho các tin nhắn hoạt động như các giá trị. Với mục đích xử lý ngoại lệ, bạn có thể muốn xác minh xem loại payload của tin nhắn bạn nhận được có phải là một khóa trong bản đồ hoặc từ điển này không. Nếu khóa đó tồn tại, bạn có thể giải tuần tự hóa tin nhắn bằng bất kỳ logic phù hợp nào.

Sau khi triển khai phương pháp như vậy, bạn có thể sử dụng nó như một callback được kích hoạt mỗi khi bạn nhận được một tin nhắn mới.

Lưu ý rằng trong ví dụ bên dưới TMessage là một kiểu chung.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
public static class MessageReceivedCallbacks
{
    public static Dictionary<int, Type> messages = new Dictionary<int, Type>
    {
        {2100, typeof(ApplicationAuthReq) },

    };

    public static TMessage ReadMessage<TMessage>(string jsonString) where TMessage : OpenAPIMessageBase
    {
        JsonDocument doc = JsonDocument.Parse(jsonString);
        int payloadType = doc.RootElement.GetProperty("payloadType").GetInt32();

        if (!messages.TryGetValue(payloadType, out var type))
            throw new Exception("This payload type is not supported");

        var result = JsonSerializer.Deserialize(jsonString, type)  as TMessage;

        return result;
    }
}

Downcasting

Phương thức ReadMessage() không thực sự trả về một lớp tin nhắn cụ thể; bạn sẽ cần xử lý downcasting riêng khi nhận một tin nhắn.

Chúng tôi thêm phương thức sau vào lớp ApplicationAuthReq của chúng tôi.

1
2
3
@staticmethod
def fromJson(jsonDct):
    return ApplicationAuthReq(clientId=jsonDct['payload']['clientId'], clientSecret=jsonDct['payload']['clientSecret'], clientMsgId=jsonDct['clientMsgId'])

Sau đó, chúng tôi thêm callback readMessage của chúng tôi và truy xuất một payload từ một từ điển.

1
2
3
4
5
6
7
8
9
class MessageReceivedCallbacks:

messagesDict = {2100: ApplicationAuthReq}

@staticmethod
def readMessage(jsonString):
    json_dct = json.loads(jsonString)
    payloadType = jsonDct['payloadType']
    return MessageReceivedCallbacks.messagesDict[payloadType].fromJson(jsonDct)

Downcasting

Vì Python là ngôn ngữ duck-typed, không cần phải xử lý downcasting riêng. Bạn có thể giải tuần tự hóa chuỗi JSON thành kiểu yêu cầu khi nhận nó.