0
votes

SWIFT 4 décodage à différents modèles d'objets JSON personnalisés

J'ai un site Web qui génère différents objets JSON. Les objets ne peuvent contenir aucun champ commun

{
    "type": "apple",
    "kind": "fruit",
    "eatable": true
}
{
    "item": "key",
    "active": true 
}
{
    "tool": "screwdriver",
    "original": "toolBox",
    "cross-head": true
}


4 commentaires

Il est très difficile de comprendre ce que vous demandez et ce qui se passe dans votre application. Recevez-vous un objet à la fois ou faites-vous une matrice ou une sorte de structure d'arbres et que voulez-vous dire que vous devez ajouter des classes ou des champs, comment est-ce pertinent pour votre question?


Tous ces objets viennent en réponse unique I.E. Un objet de réponse JSON?


Alors demandez-vous ces objets séparément? Parce que dans ce cas, vous savez à l'avance quelle sera la réponse et donc quelle classe / structure vous devrez décoder.


Non, je ne demande aucun objet qu'ils viennent quand ils veulent via des webkets. C'est pourquoi je ne sais pas quelles données j'ai eues.


3 Réponses :


4
votes

Essayez de trouver la clé que vous recherchez cette classe de modèle si cette clé n'est pas présente dans cet objet, essayez une autre classe de modèle. Cela devrait vous faire déterminer quelle classe de modèle convient à l'objet donné.

Utilisez la clé unique qui n'est présente dans aucune autre classe de modèle forte> p>

Exemple: P >

var array = NSArray(array: [[
    "type": "apple",
    "kind": "fruit",
    "eatable": true
    ],
    [
        "item": "key",
        "active": true
    ],
    [
    "tool": "screwdriver",
    "original": "toolBox",
    "cross-head": true
    ]])


for model in array as! [NSDictionary]
    {
        if(model.value(forKey: "type") != nil)
        {
            print("use Fruit Model Class")
        }
        else if(model.value(forKey: "item") != nil)
        {
            print("use second model class")
        }
        else
        {
            print("use third model class")
        }
    }


7 commentaires

Bonne décision mais j'aimerais avoir des moyens plus automatiques de choisir le modèle à utiliser. Parfois, j'ai besoin d'ajouter une nouvelle classe à mon projet afin que je vais ajouter des règles ici. Parfaitement, c'est avoir une règle à l'intérieur de la classe elle-même.


Ajouter des fonctions statiques à chaque classe pour vérifier si l'objet donné contient cette clé unique nécessaire à cette classe de modèle. Cela rendra beaucoup plus facile pour vous d'accéder et d'utiliser


Je pense que c'est le meilleur que vous puissiez faire pour déterminer le modèle de cet objet donné.


Je pense que ... malheureusement.


N'utilisez pas NSARRAY / NSDictionary et (Forge dans Swift. Vous combattez le système de type fort.


@vadian pouvez-vous aider s'il vous plaît m'aider à comprendre qu'entendez-vous par "Vous combattez le type fort".


"... système". Swift est basé sur des types puissants. Une fondation nsarray est traitée comme [tout] (non spécifié) tandis que le tableau SWIFT peut être spécifié au moins comme une éventail de dictionnaires ( [[[[chaîne: [ ] )



5
votes

Vous pouvez le faire de cette façon:

Tout d'abord, vous déclarez vos types conformes au protocole code> décodable p> xxx pré>

alors que vous étendez décodable code> pour "inverser" l'utilisation de la générosité: p> xxx pré>

vous, prolonger jsondecoder code> pour essayer des types décodables parmi ceux Vous souhaitez tester: p> xxx pré>

et, éventuellement, vous spécifiez les types que vous souhaitez essayer de décoder: p> xxx pré>

vous pouvez Ensuite, utilisez-le pour décoder votre JSON: P>

let jsonString = """
    {
        "tool": "screwdriver",
        "original": "toolBox",
        "cross-head": true
    }
    """
let jsonData = jsonString.data(using: .utf8)!

let myUnknownObject = JSONDecoder().decode(possibleTypes: decodableTypes, from: jsonData)


3 commentaires

Merci c'est ce que j'ai cherché. Extension statique pour décodable.


Décodeur: JSONDecoder = JSONDecoder () - NE PAS NE PAS CELA, JSONDecoder est actuellement en train de fuir la mémoire, si vous créez une nouvelle instance à chaque fois que vous Appelez votre méthode d'extension que vous allez avoir une tonne de mémoire fuite, mieux créer une instance globale statique pour la valeur par défaut de paramètre.


C'était juste pour garder l'exemple simple, l'idée était d'utiliser le jsondecoder sur une instance. Ce code n'est pas destiné à être utilisé de cette manière bien sûr. Mais j'ai utilisé ce raccourci pour répondre à la question clairement et ne pas décrire la manière dont jsondecoder doit être utilisé dans le code de production. Et c'est vrai même quand il n'y a pas de fuite ... merci quand même pour le rappel.



0
votes

Si tous ces champs sont liés ou un style union, vous pouvez envisager d'utiliser l'utilisateur, qui est également très facile à mettre en œuvre. xxx


0 commentaires