コンテンツにスキップ

JSONの送受信

このチュートリアルでは、JSONメッセージを送受信する方法を説明します。

TCPとWebSocket

JSONを使用する場合、TCP接続またはWebSocket接続のいずれかを使用できます。

JSONの送信

統合にJSONを使用することを選択した場合、cTraderバックエンドに有効なJSONを含む文字列を送信する必要があります。 これらの文字列として渡されるJSONオブジェクトには、以下のキーが含まれている必要があります。

キー 値のデータ型 定義
"clientMsgId" 文字列 メッセージの一意のID。 このIDはクライアント側で生成および割り当てられる必要があります。
"payloadType" 整数 メッセージを表す整数。 有効なペイロードタイプの完全なリストは、ProtoOAPayloadTypeに含まれています。
"payload" JSONオブジェクト メッセージの実際の内容を含むネストされたJSONオブジェクト。

ProtoOAApplicationAuthReqメッセージを表す有効な文字列の例を以下に示します。

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

正しいJSON文字列を送信するには、選択したプログラミング言語でシリアライゼーションのためのカスタムメカニズムを作成する必要があります。

以下の例では、シリアライゼーションを処理するためのいくつかのアプローチを定義しています。 選択したプログラミング言語とデザインパターンに応じて、独自の実装を作成できます(そして作成すべきです)。

以下では、2つのベースクラスを定義し、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;
}

すべてのOpen APIメッセージのベースクラスを作成し、デモンストレーション目的で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})

必要なロジックを実装した後、これらのメッセージを表すクラスの新しいインスタンスを作成し、それらを選択したTCPまたはWebSocketクライアントに渡すことで、cTraderバックエンドに新しいメッセージを送信できるようになります。

JSONの受信

JSONメッセージを受信および処理するには、JSON文字列をOpen APIメッセージの表現にデシリアライズするメソッドを実装する必要があります。

このメソッドを実装する際に、ペイロードタイプをキーとし、メッセージを表すクラスの名前を値とするマップ(または辞書)を初期化することが役立つ場合があります。 例外処理の目的で、受信したメッセージのペイロードタイプがこのマップまたは辞書のキーであるかどうかを確認することが望ましい場合があります。 そのようなキーが存在する場合、適切なロジックを使用してメッセージをデシリアライズできます。

このようなメソッドを実装した後、新しいメッセージを受信するたびにトリガーされるコールバックとして使用できます。

以下の例では TMessage はジェネリック型であることに注意してください。

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

ダウンキャスト

ReadMessage() メソッドは実際には特定のメッセージクラスを返しません。メッセージを受信する際にダウンキャストを別途処理する必要があります。

ApplicationAuthReq クラスに以下のメソッドを追加します。

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

その後、readMessage コールバックを追加し、辞書からペイロードを取得します。

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)

ダウンキャスト

Pythonはダックタイピングであるため、ダウンキャストを別途処理する必要はありません。 受信時にJSON文字列を必要なタイプにデシリアライズできます。