Lewati ke isi

Kirim dan terima JSON

Dalam tutorial ini, kami menjelaskan bagaimana Anda dapat mengirim dan menerima pesan JSON.

TCP dan WebSocket

Saat bekerja dengan JSON, Anda dapat menggunakan koneksi TCP atau koneksi WebSocket.

Kirim JSON

Jika Anda memilih untuk menggunakan JSON dalam integrasi Anda, Anda harus mengirim string yang berisi JSON yang valid ke backend cTrader. Objek JSON yang diteruskan sebagai string ini harus berisi kunci berikut.

Kunci Tipe data nilai Definisi
"clientMsgId" string ID unik dari sebuah pesan. ID ini harus dibuat dan ditetapkan di sisi klien.
"payloadType" integer Integer yang mewakili pesan. Daftar lengkap jenis payload yang valid termasuk dalam ProtoOAPayloadType.
"payload" Objek JSON Objek JSON bersarang yang berisi konten sebenarnya dari pesan.

Contoh string yang valid (mewakili pesan ProtoOAApplicationAuthReq) dapat ditemukan di bawah ini.

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

Untuk mengirim string JSON yang benar, Anda perlu membuat mekanisme serialisasi khusus dalam bahasa pemrograman pilihan Anda.

Dalam contoh di bawah ini, kami mendefinisikan beberapa pendekatan untuk menangani serialisasi. Anda dapat (dan harus) mengimplementasikan sendiri tergantung pada bahasa pemrograman dan pola desain yang Anda pilih.

Di bawah ini, kami mendefinisikan dua kelas dasar dan kemudian membuat representasi khusus dari pesan 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;
}

Kami membuat kelas dasar untuk semua pesan Open API dan, untuk tujuan demonstrasi, mendefinisikan kelas untuk 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})

Setelah mengimplementasikan logika yang diperlukan, Anda seharusnya dapat mengirim pesan baru ke backend cTrader dengan membuat instance baru dari kelas yang mewakili pesan ini dan kemudian meneruskannya ke klien TCP atau WebSocket pilihan Anda.

Terima JSON

Untuk menerima dan memproses pesan JSON, Anda harus mengimplementasikan metode untuk mendeserialisasi string JSON menjadi representasi pesan Open API.

Untuk mengimplementasikan metode ini, Anda mungkin merasa membantu untuk menginisialisasi peta (atau kamus) di mana jenis payload dapat menjadi kunci dengan nama kelas yang mewakili pesan bertindak sebagai nilai. Untuk tujuan penanganan pengecualian, Anda mungkin ingin memverifikasi apakah jenis payload dari pesan yang Anda terima adalah kunci dalam peta atau kamus ini. Jika kunci tersebut ada, Anda dapat mendeserialisasi pesan menggunakan logika yang sesuai.

Setelah mengimplementasikan metode seperti itu, Anda dapat menggunakannya sebagai callback yang dipicu setiap kali Anda menerima pesan baru.

Perhatikan bahwa dalam contoh di bawah ini TMessage adalah tipe generik.

 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

Metode ReadMessage() sebenarnya tidak mengembalikan kelas pesan tertentu; Anda perlu menangani downcasting secara terpisah saat menerima pesan.

Kami menambahkan metode berikut ke kelas ApplicationAuthReq kami.

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

Kami kemudian menambahkan callback readMessage kami dan mengambil payload dari kamus.

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

Karena Python bersifat duck-typed, tidak perlu menangani downcasting secara terpisah. Anda dapat mendeserialisasi string JSON ke tipe yang diperlukan saat menerimanya.