moozzyk / SignalR-Client-Swift

Swift SignalR Client for Asp.Net Core SignalR server
MIT License
351 stars 132 forks source link

Unable to get values from ArgumentExtractor #265

Closed aarons2222 closed 1 year ago

aarons2222 commented 1 year ago

Always getting a decoding error as values are empty, despite receiving message as printed in debug lo g. Am I misunderstanding the use of this?

self.chatHubConnection!.on(method: "SendMessage", callback: { (payload: ArgumentExtractor?) in
            let response = try! payload?.getArgument(type: MessageR.self)
            print("Response: \(payload)")
   })

Struct

struct MessageR: Codable {
    struct Id: Codable {
        let timestamp: Int
        let machine: Int
        let pid: Int
        let increment: Int
        let creationTime: String
    }
    struct Body: Codable {
        let text: String
        let fromInside: Bool
        let timestamp: String
        let messageId: String
        let status: Int
        let read: Bool
    }
    struct Argument: Codable {
        let _id: Id
        let pin: Int
        let pan: String
        let body: Body
    }
    let type: Int
    let target: String
    let arguments: [Argument]
}

//ERROR

keyNotFound(CodingKeys(stringValue: "type", intValue: nil), Swift.DecodingError.Context(codingPath: [_JSONKey(stringValue: "Index 0", intValue: 0)], debugDescription: "No value associated with key CodingKeys(stringValue: \"type\", intValue: nil) (\"type\").", underlyingError: nil))

moozzyk commented 1 year ago

Please provide logs and show the JSON you are trying to process. The error message indicates that the type property is missing but possibly it shows up because it is just the first property in the struct.

aarons2222 commented 1 year ago

Thanks for getting back to me so promptly.

{
  "type": 1,
  "target": "SendMessage",
  "arguments": [
    {
      "_id": {
        "timestamp": 1673433892,
        "machine": 13501675,
        "pid": 27108,
        "increment": 11139807,
        "creationTime": "2023-01-11T10:44:52Z"
      },
      "pin": 888888,
      "pan": "07447000599",
      "body": {
        "text": "Hi there",
        "fromInside": true,
        "timestamp": "2023-01-11T10:44:52.321681Z",
        "messageId": "b0ae4cdb-5094-4315-847f-466eb8d8367c",
        "status": 100,
        "read": false
      }
    }
  ]
}
moozzyk commented 1 year ago

This is the payload the client receives and not the payload you get. You should not try deserialize it. You should only worry about arguments your server is sending. You can take a look at the tests. The server defines a struct:

https://github.com/moozzyk/SignalR-Client-Swift/blob/0e7a67e2a41e3c2f769406d344ef1f72720ed98f/Examples/TestServer/Person.cs#L5-L12 and sends it to the client:

https://github.com/moozzyk/SignalR-Client-Swift/blob/0e7a67e2a41e3c2f769406d344ef1f72720ed98f/Examples/TestServer/TestHub.cs#L43

and the client only defines a counterpart struct: https://github.com/moozzyk/SignalR-Client-Swift/blob/0e7a67e2a41e3c2f769406d344ef1f72720ed98f/Tests/SignalRClientTests/HubConnectionTests.swift#L809-L815

and reads it: https://github.com/moozzyk/SignalR-Client-Swift/blob/0e7a67e2a41e3c2f769406d344ef1f72720ed98f/Tests/SignalRClientTests/HubConnectionTests.swift#L734-L743

In other words you only need to take care of what is in the Arguments array from the payload.

Also, you don't need to use argumentExtractor (even though the test does). This is a lower level API. You should be able to get away with this (I am using the name Argument here because this is how your struct is named - you would probably want to rename your struct to something more meaningful):

self.chatHubConnection!.on(method: "SendMessage", callback: { (arg: Argument) in
 print(arg.pin)
 // ...
   })
aarons2222 commented 1 year ago

Thank you, that makes sense.