Zum Inhalt

JSON senden und empfangen

In diesem Tutorial erklären wir, wie Sie JSON-Nachrichten senden und empfangen können.

TCP und WebSocket

Bei der Arbeit mit JSON können Sie entweder eine TCP-Verbindung oder eine WebSocket-Verbindung verwenden.

JSON senden

Wenn Sie sich für die Verwendung von JSON in Ihrer Integration entscheiden, müssen Sie Zeichenfolgen mit gültigem JSON an das cTrader-Backend senden. Die als diese Zeichenfolgen übergebenen JSON-Objekte müssen die folgenden Schlüssel enthalten.

Schlüssel Wertdatentyp Definition
"clientMsgId" string Die eindeutige ID einer Nachricht. Diese ID muss auf der Client-Seite generiert und zugewiesen werden.
"payloadType" integer Die Ganzzahl, die die Nachricht darstellt. Eine vollständige Liste gültiger Payload-Typen ist in ProtoOAPayloadType enthalten.
"payload" JSON-Objekt Ein verschachteltes JSON-Objekt, das den tatsächlichen Inhalt der Nachricht enthält.

Ein Beispiel für eine gültige Zeichenfolge (die die Nachricht ProtoOAApplicationAuthReq darstellt) finden Sie unten.

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

Um korrekte JSON-Zeichenfolgen zu senden, müssen Sie einen benutzerdefinierten Mechanismus für die Serialisierung in Ihrer gewählten Programmiersprache erstellen.

In den folgenden Beispielen definieren wir mehrere Ansätze zur Handhabung der Serialisierung. Sie können (und sollten) Ihre eigene Implementierung abhängig von Ihrer bevorzugten Programmiersprache und Ihrem/Ihren Entwurfsmuster(n) erstellen.

Im Folgenden definieren wir zwei Basisklassen und erstellen dann eine benutzerdefinierte Darstellung der Nachricht 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;
}

Wir erstellen eine Basisklasse für alle Open API-Nachrichten und definieren zu Demonstrationszwecken die Klasse für 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})

Nach der Implementierung der erforderlichen Logik sollten Sie in der Lage sein, neue Nachrichten an das cTrader-Backend zu senden, indem Sie neue Instanzen der Klassen erstellen, die diese Nachrichten darstellen, und diese dann an Ihren bevorzugten TCP- oder WebSocket-Client übergeben.

JSON empfangen

Um JSON-Nachrichten zu empfangen und zu verarbeiten, müssen Sie eine Methode zur Deserialisierung einer JSON-Zeichenfolge in eine Darstellung einer Open API-Nachricht implementieren.

Um diese Methode zu implementieren, kann es hilfreich sein, eine Map (oder ein Dictionary) zu initialisieren, in der Payload-Typen als Schlüssel mit den Namen der Klassen, die Nachrichten darstellen, als Werte fungieren können. Für Zwecke der Ausnahmebehandlung möchten Sie möglicherweise überprüfen, ob der Payload-Typ der empfangenen Nachricht ein Schlüssel in dieser Map oder diesem Dictionary ist. Wenn ein solcher Schlüssel existiert, können Sie die Nachricht mit einer beliebigen geeigneten Logik deserialisieren.

Nach der Implementierung einer solchen Methode können Sie diese als Callback verwenden, der jedes Mal ausgelöst wird, wenn Sie eine neue Nachricht empfangen.

Beachten Sie, dass im folgenden Beispiel TMessage ein generischer Typ ist.

 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;
    }
}

Hinweis" „Downcasting

Die Methode ReadMessage() gibt nicht tatsächlich eine spezifische Nachrichtenklasse zurück; Sie müssen das Downcasting separat behandeln, wenn Sie eine Nachricht empfangen.

Wir fügen unserer Klasse ApplicationAuthReq die folgende Methode hinzu.

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

Wir fügen dann unseren Callback readMessage hinzu und rufen eine Payload aus einem Dictionary ab.

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)

Hinweis" „Downcasting

Da Python duck-typed ist, ist es nicht erforderlich, das Downcasting separat zu behandeln. Sie können die JSON-Zeichenfolge beim Empfang in den erforderlichen Typ deserialisieren.