Парсинг не валидного JSON


#1

Мне приходит вот такое из сервера

        {
            id = "a5q25-a2a1a5";
            jsonrpc = "2.0";
            result =     {
                data =         {
                    coins = 545;
                    freePokes = 0;
                };
                id = "<null>";
                success = 1;
            };
        }

Мне нужно это распарсить coins и success

Мне необходимо использовать Decodable
Вот моя модель:

struct BaseResultData: Decodable {
    
    let coins: Int
    let success: Bool

    enum CodingKeys: String, CodingKey {
        case coins
        case success
    }
    
    init(from decoder: Decoder) throws {
        let values = try decoder.container(keyedBy: CodingKeys.self)
        coins = try values.decode(Int.self, forKey: .coins)
        success = try values.decode(Bool.self, forKey: .success)
    }
}

примерно вот так я это делаю:

 guard let dict = result as? [String : Any],
                    let data = dict["data"]
                    else {
                        completionHandler(.failure(.parsError))
                        return
                }
                
                // get coins, success
                guard let dataCoins = data as? [String : Any],
                    let coins = dataCoins["coins"],
                    let success = dict["success"]
                    else {
                        completionHandler(.failure(.parsError))
                        return
                }
                
                let dictResult = ["coins" : coins, "success" : success]
                let strJsonData = dictResult.json
                print("strJsonData = \(strJsonData)")
                let jsonData = strJsonData.data(using: .utf8)!
                completionHandler(.success(jsonData))

Забираю значения по ключу и формирую новый валидный json и отправляю его в модель, получается такое:

{
  "coins" : 545,
  "success" : true
}

Не могу распарсить, подскажите что я делаю не правильно


#2

а в чем проблема использовать чистый декодабл

import UIKit

let data = """
{
    "id": "a5q25-a2a1a5",
    "jsonrpc": "2.0",
    "result": {
        "data": {
            "coins": 545,
            "freePokes": 0
        },
        "id": "<null>",
        "success": 1
    }
}
"""

struct Data: Decodable {
    let coins: Int
    let freePokes: Int
}


struct Res: Decodable {
    let data: Data?
    let id: String?
    let success: Bool
    
    enum CodingKeys: String, CodingKey {
        case data
        case id
        case success
    }
    
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)
        
        self.data = try? container.decode(Data.self, forKey: .data)
        self.id = try? container.decode(String.self, forKey: .id)
        let success = (try? container.decode(Int.self, forKey: .success)) ?? 1
    self.success = Bool(NSNumber(value: success))
    }
}

struct Model: Decodable {
    let id: String
    let jsonrpc: String
    let result: Res
}

let m = try JSONDecoder().decode(Model.self, from: data.data(using: .utf8)!)

print(m)

#3

То что вы написали парсится, а вот с реальными данными из сервера нет, используется json-rpc, получаю такой формат

   {
            id = "a5q25-a2a1a5";
            jsonrpc = "2.0";
            result =     {
                data =         {
                    coins = 545;
                    freePokes = 0;
                };
                id = "<null>";
                success = 1;
            };
        }

#4

Сочувствую вам.
Как вариант, перед обработкой ответа, можно заменить все ";" на ","


#5
let plist = """
{
           id = "a5q25-a2a1a5";
           jsonrpc = "2.0";
           result =     {
               data =         {
                   coins = 545;
                   freePokes = 0;
               };
               id = "<null>";
               success = 1;
           };
       }
"""

struct Container: Decodable {
    struct Result: Decodable {
        struct Data: Decodable {
            let coins: String
        }
        let data: Data
        let success: String
    }
    let id: String
    let result: Result
}

let result = try PropertyListDecoder().decode(Container.self, from: plist.data(using: .utf8)!)

print(result)