0
votes

Décodage de la structure JSON dynamique à Swift 4

J'ai le problème suivant que je ne suis pas sûr de savoir comment gérer.

mon JSON code> La réponse peut ressembler à ceci: p> xxx pré>

Ou comme ceci: p> xxx pré>

ainsi en bref, les données peuvent être un seul objet ou un tableau. Ce que j'ai, c'est ceci: p> xxx pré>

Ceci fonctionne correctement pour le premier cas d'utilisation, mais il échouera une fois que les données se transforme dans P>

: [DataObject?] Code> P>

Comment puis-je faire cette dynamique sans duplication de code? P>

EDIT: Voici comment je déco de décoder l'objet aussi bien p>

 func makeDataTaskWith(with urlRequest: URLRequest, completion: @escaping(_ apiData: ApiData?) -> ()) {
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    session.dataTask(with: urlRequest) {
        (data, response, error) in
        guard let _ = response, let data = data else {return}

        if let responseCode = response as? HTTPURLResponse {
            print("Response has status code: \(responseCode.statusCode)")
        }

        do {
            let retreived = try NetworkManager.shared.decoder.decode(ApiData.self, from: data)
            completion(retreived)
        } catch let decodeError as NSError {
            print("Decoder error: \(decodeError.localizedDescription)\n")
            return
        }
        }.resume()
}


6 commentaires

Et qu'est-ce que l'API envoie en cas d'erreur ! = Null ?


@Vadian Il envoie une chaîne, vous pouvez voir que dans la structure des apidata.


@ROBERTDRESLER Je ne suis pas sûr de comprendre la question? Avec l'aide des apidata de struct qui se conformait au protocole décodable


@ROBERTDRESLER J'ai édité le message pour répondre à votre question.


Utiliser la puissance de générique


Voir-> Stackoverflow.com/a/50674899/6630644


4 Réponses :


1
votes

Si vous n'avez que deux résultats possibles pour vos données, une option serait d'essayer d'analyser les données à l'un des types attendus, si cela échoue, vous savez que les données sont d'autres types et que vous pouvez le gérer en conséquence.

voir Ce < / p>


1 commentaires

Oui mais que cela dupliquerait le code, les deux types auraient Var Userid: int? et un tas d'autres informations utilisateur que je n'ai pas collées dans l'exemple ci-dessus.



0
votes

Vous pouvez essayer xxx


xxx

2 commentaires

Merci, mais cela n'évite pas la duplication. Les Structs Datum et DataClass ont laissé l'identité.


vous pouvez les faire 1 mais devrait faire jeton facultatif si vous voulez



3
votes

Si DATA CODE> peut être un seul objet ou un tableau Écrire un initialiseur personnalisé qui décode d'abord un tableau, si une erreur d'inadéquation de type se produit décoder un seul objet. DATA code> est déclaré comme une matrice de toute façon.

comme jeton code> apparaît uniquement dans un seul objet que la propriété est déclarée en option. P>

func makeDataTaskWith(with urlRequest: URLRequest, completion: @escaping(ApiData?, Error?) -> Void) {
    let config = URLSessionConfiguration.default
    let session = URLSession(configuration: config)

    session.dataTask(with: urlRequest) {
        (data, response, error) in
        if let error = error { completion(nil, error); return }

        if let responseCode = response as? HTTPURLResponse {
            print("Response has status code: \(responseCode.statusCode)")
        }

        do {
            let retreived = try NetworkManager.shared.decoder.decode(ApiData.self, from: data!)
            completion(retreived, nil)
        } catch {
            print("Decoder error: ", error)
            completion(nil, error)
        }
        }.resume()
}


2 commentaires

C'est ce que je cherchais, je ne savais pas de décodingerror.typeMismatic. Merci!


Vous avez toujours cloué une réponse quand il s'agit de codable



2
votes

Utilisation de la puissance de générique code>, il est simple comme ci-dessous: xxx pré>

Utilisez strong> p>

if let obj = try? NetworkManager.shared.decoder.decode(ApiData<DataObject>.self, from: data) {
    //Do somthing
} else if let array = try NetworkManager.shared.decoder.decode(ApiData<[DataObject]>.self, from: data) {
    // Do somthing
}


0 commentaires