Partage
  • Partager sur Facebook
  • Partager sur Twitter

Swift: deserializer JSON en conservant l'ordre

18 avril 2019 à 11:09:39

Bonjour,

Je suis face a un petit soucis.
J'utilise ce code pour deserialize du JSON:

if let jsonLanguages =  self.currentLanguagesData as? String {

                let json = jsonLanguages.data(using: .utf8)!
            
                do {
                    if let jsonArray = try JSONSerialization.jsonObject(with: json, options : .allowFragments) as? [Dictionary<String,String>] {
                        
                        if jsonArray[0] != nil {
                            
                            print("---------------------------")
                            print(self.currentLanguagesData)
                            print("----")
                            print(jsonArray[0])
                            print("---------------------------")

Apres des series de bug, je realise que jsonArray[0] n'est jamais dans le bon ordre.

Exemple: Je lance le programme une premiere fois et j'obtiens ceci dans la console

Je relance le programme mais cette fois j'obtiens ceci dans la console:

Apres quelque reecherche je suis tombe sur ce post: https://stackoverflow.com/questions/31088973/dictionary-wrong-order-json

En gros si je comprend bien, il ne faut pas utiliser Dictionnary (mais un Array)
Ok ... mais dans ce cas la qu'est ce que je peux ecrire a la place de as? [Dictionary<String,String>] ?

Pouvez vous me donner un coup de main?

  • Partager sur Facebook
  • Partager sur Twitter
18 avril 2019 à 14:29:24

Salut,
Effectivement, les dictionnaires ne sont pas ordonnés en Swift. La première question qu'il faut se poser c'est : "Est-ce que l'ordre a vraiment une importance ?". Quand je regarde tes données, j'ai pas vraiment l'impression. Mais supposons que la réponse soit oui. Dans ce cas tu peux faire ta propre implémentation de dictionnaire trié. "Swift linked map" sur Google par exemple. Tu tomberais sur des trucs comme ça : https://www.timekl.com/blog/2014/06/02/learning-swift-ordered-dictionaries
  • Partager sur Facebook
  • Partager sur Twitter
19 avril 2019 à 6:07:59

@Geda:merci pour ta reponse

Tu vas pouvoir me donner une piste de reflexion. Mon application iOS utilise une API. Pour mettre a jour les langues, je dois fournir un JSON contenant la liste des langues. Ce JSON est tres simple. Par exemple:

[{"en-GB":"3","ms":"0","am":"0"}]

Jusque la tout est ok.

Pour mettre a jour les langues dans mon application maintenant, je dois recuperer le JSON.
Ca c'est ok.
Je dois ensuite faire une iteration sur la liste des langues (d'ou le code plus haut).
Peut etre que je m'y prend mal mais la je ne vois pas vraiment comment faire ca.

En Javascript ca donnerait ca:

var obj = JSON.parse('[{"en-GB":"3","ms":"0","am":"0"}]');

En Php ca donnerait ca:

$obj = json_decode('[{"en-GB":"3","ms":"0","am":"0"}]');

Dans ces 2 cas, l'ordre est conserve. en-GB est avant am

J'aimerai obtenir le meme comportement en Swift.

Je ne vois pas du tout comment decoder un JSON sans utiliser de struct (et donc decoder).
En effet, la structure du JSON va dependre de l'API que je ne peux pas modifier...

Dans tous les exemples que je trouve, ils partent du principe que l'on connait a l'avance la structure du JSON et donc que l'on peut faire quelque chose de la forme: 

let jsonDecoder = JSONDecoder()
let employee2 = try jsonDecoder.decode(Employee.self, from: jsonData)


Source: 

https://www.raywenderlich.com/382-encoding-decoding-and-serialization-in-swift-4

C'est super si tu as la structure de Employee et que jsonData respecte cette structure.
Dans mon cas, je ne connais pas la structure du JSON a l'avance mais j'aimerai recuperer les donnees.
Qui plus et quand bien meme je connaitrai la structure du JSON, elle pourrait changer a n'importe quelle moment (car je n'ai pas la main sur l'API) causant un crach de mon application...

-
Edité par Scion 19 avril 2019 à 7:44:51

  • Partager sur Facebook
  • Partager sur Twitter
19 avril 2019 à 22:21:12

Salut,

J'ai bien peur de ne pas comprendre du tout ta problématique.

Une API fournit un contrat d'interface. Même si on a pas la main sur l'API (c'est rarement le cas en vrai) on connait tout de même le format avec lequel l'API répond.

En quoi cela est-il si important que "en-GB" soit en premier ? Je pige pas. La clé change ?

Comme je disais, il y a des solutions pour implémenter son propre dictionnaire trié. cf le lien que j'ai donné.

Sinon, tu as SwiftyJSON qui te permet d'accéder aux éléments d'un son sans "struct" (même si je vois pas bien en quoi ça peut t'aider. De toute façon j'ai pas compris le problème.)

  • Partager sur Facebook
  • Partager sur Twitter
20 avril 2019 à 1:14:47

"En quoi cela est-il si important que "en-GB" soit en premier ? Je pige pas. La clé change ?"

Si dans le fichier JSON l'ordre est : en-GB, ms, fr-FR, am
eh bien dans mon application je dois creer une liste de langues dans exactement le meme ordre.
C'est a dire :

- en-GB
- ms
- fr-FR
- am

Est ce que tu comprends ?

  • Partager sur Facebook
  • Partager sur Twitter
20 avril 2019 à 10:25:41

Ah j’avais pas compris que am et ms etaient des Langues. je vois pas bien pourquoi elles sont encapsulés dans un Array mais c’est pas grave. 

Prend mon lien si tu veux faire un dictionnaire trié

  • Partager sur Facebook
  • Partager sur Twitter