0

In my new project that act like a RPC, in some moment i receive a JSON with function name and a list of parameters. Example:

{
  "f": "sample.login",
  "p": [
     {"n": "param1", "v": "value1"},
     {"n": "param2", "v": true},
     {"n": "param3", "v": {"id": 1, "title": "title xyz"}}
     [...] any amount of params [...]
  ]
}

In other moments, i need create the same structure and encode as JSON. Example:

public class Param: Codable {
    public var n: String
    public var v: Any?
    
    init(n: String, v: Any?) {
        self.n = n
        self.v = v
    }
}

struct Todo: Codable {
    var id: Int64
    var title: String
    var data: [String: String]
    var done: Bool
}


public class JsonSerializer: Serializer {
    private var decoder = JSONDecoder()
    private var encoder = JSONEncoder()

    public func encodeRequest(functionName: String, params: [Param]) -> String {
        do {
            let request = JsonRequestData(f: functionName, p: params)
            let data = try encoder.encode(request)
            
            if let result = String(data: data, encoding: .utf8) {
                return result
            } else {
                print("[JsonSerializer : encodeRequest] Error when try to encode data")
            }
        } catch let e {
            print("[JsonSerializer : encodeRequest] Error when try to encode data: \(e.localizedDescription)")
        }
        
        return ""
    }

    struct JsonRequestData: Codable {
        let f: String
        var p: [Param]

        init(f: String, p: [Param]) {
            self.f = f
            self.p = p
        }
    }
}

let todo = Todo(id: 1, title: "Title 1", data: [:], done: true)
let name = "sample.todo.single"

var params: [Param] = []
params.append(Param(n: "suffix", v: "%"))
params.append(Param(n: "p2", v: todo))

let s = JsonSerializer()
let json = s.encodeRequest(functionName: name, params: params)
print(json)

I made it work in C++ (nlohmann json) and Kotlin (with gson). Only left make it work in Swift.

I know of course Swift doesn't support encoding ANY type. And I'm aware of some limitations on this in Swift.

But I would like to find a plausible solution to my problem.

Even if the user has to implement a protocol on his side for his types, or enter his type in a list of known types or something.

The project is at this URL, if you want to see the codes in more depth: https://github.com/xplpc/xplpc

Removing this lock, the code is practically ready.

I tried on Apple forums, search on Google and on iOS group inside Slack.

desertnaut
  • 57,590
  • 26
  • 140
  • 166
  • Is `v` value always of the same kind? You could use an enum with associatedValue to manage the different values. – Larme Oct 26 '22 at 08:05
  • No, this is a library, so i can't fix the types of values. Can be any user type. – Paulo Coutinho Oct 26 '22 at 10:01
  • 1
    Given your comment to the answer below it’s not clear what you want. In the json above you have different types in the array but in the comment below you say it’s always one specific type in the array? So for a given json message (function), do you have one type of parameters in the array or multiple types? – Joakim Danielson Oct 26 '22 at 10:24

1 Answers1

-1

Thanks for answers.

But after try a lot, i decide to use AnyCodable project (https://github.com/Flight-School/AnyCodable) with my modifications (https://github.com/xplpc/xplpc/tree/main/swift/lib/Sources).

AnyCodable let me use all swift types and if i use these types on my class/struct it works without problems.

To use any custom type, only need add more lines on AnyEncodable and AnyDecodable class.

Thanks.