Langkau tajuk talian

Hantar dan terima JSON

Dalam tutorial ini, kami menerangkan bagaimana anda boleh menghantar dan menerima mesej JSON.

TCP dan WebSocket

Apabila bekerja dengan JSON, anda boleh menggunakan sama ada sambungan TCP atau sambungan WebSocket.

Hantar JSON

Jika anda memilih untuk menggunakan JSON dalam integrasi anda, anda perlu menghantar rentetan yang mengandungi JSON yang sah ke sistem bahagian belakang cTrader. Objek JSON yang diluluskan sebagai rentetan ini perlu mengandungi kunci berikut.

Kunci Jenis data nilai Definisi
"clientMsgId" rentetan ID unik mesej. ID ini perlu dijana dan ditetapkan di pihak klien.
"payloadType" integer Integer yang mewakili mesej. Senarai penuh jenis muatan yang sah disertakan dalam ProtoOAPayloadType.
"payload" Objek JSON Objek JSON bersarang yang mengandungi kandungan sebenar mesej.

Contoh rentetan yang sah (mewakili mesej ProtoOAApplicationAuthReq) boleh didapati di bawah.

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

Untuk menghantar rentetan JSON yang betul, anda perlu mewujudkan mekanisme penyiratan tersuai dalam bahasa pengaturcaraan pilihan anda.

Dalam contoh di bawah, kami mentakrifkan beberapa pendekatan untuk mengendalikan penyiratan. Anda boleh (dan harus) melaksanakan pendekatan anda sendiri bergantung pada bahasa pengaturcaraan dan corak reka bentuk pilihan anda.

Di bawah, kami mentakrifkan dua kelas asas dan kemudian mewujudkan perwakilan tersuai mesej 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 mewujudkan kelas asas untuk semua mesej Open API dan, untuk tujuan demonstrasi, mentakrifkan 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 melaksanakan logik yang diperlukan, anda sepatutnya boleh menghantar mesej baharu ke sistem bahagian belakang cTrader dengan mewujudkan contoh baharu kelas yang mewakili mesej ini dan kemudian menghantarnya ke klien TCP atau WebSocket pilihan anda.

Terima JSON

Untuk menerima dan memproses mesej JSON, anda perlu melaksanakan kaedah untuk menyahserat rentetan JSON ke dalam perwakilan mesej Open API.

Untuk melaksanakan kaedah ini, anda mungkin mendapati berguna untuk memulakan peta (atau kamus) di mana jenis muatan boleh menjadi kunci dengan nama kelas yang mewakili mesej bertindak sebagai nilai. Untuk tujuan pengendalian pengecualian, anda mungkin ingin mengesahkan sama ada jenis muatan mesej yang anda terima adalah kunci dalam peta atau kamus ini. Jika kunci sedemikian wujud, anda boleh menyahserat mesej menggunakan sebarang logik yang sesuai.

Setelah melaksanakan kaedah sedemikian, anda boleh menggunakannya sebagai panggilan balik yang dicetuskan setiap kali anda menerima mesej baharu.

Perhatikan bahawa dalam contoh di bawah TMessage adalah jenis 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;
    }
}

Penurunan jenis

Kaedah ReadMessage() sebenarnya tidak mengembalikan kelas mesej tertentu; anda perlu mengendalikan penurunan jenis secara berasingan apabila menerima mesej.

Kami menambah kaedah 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 menambah panggilan balik readMessage kami dan mengambil muatan 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)

Penurunan jenis

Oleh kerana Python adalah jenis itik, tidak perlu mengendalikan penurunan jenis secara berasingan. Anda boleh menyahserat rentetan JSON ke dalam jenis yang diperlukan apabila menerimanya.