IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

Désérialiser un objet contenant JSON contenant une structure d'objets


Sujet :

C#

  1. #1
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut Désérialiser un objet contenant JSON contenant une structure d'objets
    Bonjour,

    J'essaie de consommer un service REST dont voici la description :
    https://developers.lucca.fr/fr/api/d...ts/departments

    En soit, rien de bien compliqué.

    Pour se faire, je suis un exemple de Microsoft :
    https://docs.microsoft.com/en-us/dot...e-webapiclient

    J'arrive bien à la fin du tuto sans problème.

    Sauf que pour mettre les deux en musique, c'est moins simple...
    En effet, si le webservice du tuto renvoie une liste d'objet "simple", mon webservice ici me renvoie plusieurs objets.

    Et force est de constater qu'une fois que mon objet est désérialisé (sans erreur) j'ai que des "null" dans mes propriétés...

    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
     
            public static async Task<List<Department>> GetDepartments()
            {
                client.DefaultRequestHeaders.Accept.Clear();
                client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("*/*"));
                client.DefaultRequestHeaders.Add("Authorization", $"Lucca application={api_key}");
     
                var streamTask = client.GetStreamAsync(string.Concat(url, Department.PATH));
     
                var departmentresponse = await JsonSerializer.DeserializeAsync<Department.DepartmentResponse>(await streamTask);
                return departmentresponse.Data.Items.ToList();
            }
     
     
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Net.Http.Headers;
    using System.Text.Json;
    using System.Text.Json.Serialization;
    using System.Threading.Tasks;
     
     
    namespace FiggoSync
    {
        internal class Department
        {
            public const string PATH = "/api/v3/departments";
     
            /*
                "id":11,
                "name":"Support",
                "url":"https://sandbox.ilucca-demo.net/api/v3/departments/11"
            */
     
            [JsonPropertyName("id")]
            public int? Id;
     
            [JsonPropertyName("name")]
            public string? Name;
     
            internal class DepartmentResponse
            {
                [JsonPropertyName("header")]
                public Header? Header;
     
                [JsonPropertyName("data")]
                public Data? Data;
            }
     
            internal class Header
            {
                [JsonPropertyName("generated")]
                public DateTime? Generated;
            }
     
            internal class Data
            {
                [JsonPropertyName("items")]
                public Department[]? Items;
            }
        }
    }

    Une idée de ce qu'il faut que je modifie pour que ça veuille bien marcher ?

  2. #2
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Hmpf... Manquait juste les { get; set; }

    Quand on sait pas recopier un exemple...

  3. #3
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2014
    Messages
    218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Août 2014
    Messages : 218
    Points : 493
    Points
    493
    Par défaut
    Bonjour

    Peut on voir la source de la classe C# de Department ?

    EDIT : messages qui se sont croisés; c'est exactement ce que je voulais voir, les getter/setter.

  4. #4
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Points : 10 543
    Points
    10 543
    Billets dans le blog
    21
    Par défaut
    Du coup, je me pose la question suivante : pourquoi l'utilisation de l'attribut JsonPropertyName n'est pas restreint à une propriété (comme son nom l'indique). Si cela avait été le cas, tu te serais vite rendu compte de l'erreur en essayant d'appliquer JsonPropertyName à un attribut (=champ)

    Peut être une remontée à faire upstream, même si cela risque d'être rejeté pour cause de rupture de compatibilité (une mise à jour pourrait empêcher la compilation à cause d'attribut mal appliqué).

  5. #5
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2014
    Messages
    218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Août 2014
    Messages : 218
    Points : 493
    Points
    493
    Par défaut
    Citation Envoyé par François DORIN Voir le message
    Du coup, je me pose la question suivante : pourquoi l'utilisation de l'attribut JsonPropertyName n'est pas restreint à une propriété (comme son nom l'indique). Si cela avait été le cas, tu te serais vite rendu compte de l'erreur en essayant d'appliquer JsonPropertyName à un attribut (=champ)

    Peut être une remontée à faire upstream, même si cela risque d'être rejeté pour cause de rupture de compatibilité (une mise à jour pourrait empêcher la compilation à cause d'attribut mal appliqué).
    Dans la mesure où on n'a pas la source de sa classe, qu'est ce qui permet de dire que JsonPropertyName ( qui a effectivement l'attribut target Field en sus de Property) ne fonctionne pas sur un champ public ?

  6. #6
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Points : 10 543
    Points
    10 543
    Billets dans le blog
    21
    Par défaut
    Si si, on a la source de sa classe

    Par contre, il est étonnant que l'attribut JsonPropertyName ait le target Field s'il ne fonctionne pas sur les champs. Car s'il fonctionnait, il n'aurait pas eu de souci avec son code initial.

  7. #7
    Membre confirmé
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Août 2014
    Messages
    218
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : Consultant informatique

    Informations forums :
    Inscription : Août 2014
    Messages : 218
    Points : 493
    Points
    493
    Par défaut
    Citation Envoyé par François DORIN Voir le message
    Si si, on a la source de sa classe .
    Je n’avais pas scrollé le code ....

    Par contre, je note que la classe est "internal" alors que les sérializers sont par définition externes à l'assembly où elle est déclarée.

    Peut être tester avec la class à public.

  8. #8
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Points : 10 543
    Points
    10 543
    Billets dans le blog
    21
    Par défaut
    Effectivement, les classes sont internal. Cela ne gêne pourtant pas vraiment, car les notions de visibilité sont utilisés lors de la compilation. Pour la sérialisation/désérialisation, ce qui est utilisée, c'est la réflexion, qui permet de passer outre ces vérifications d'accès...

  9. #9
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Oulà, bonjour,

    Vous avez continué à discuter sans moi

    J'en profite pour poser une petite question liée à mon souci initial.

    Maintenant j'arrive à consommer l'API de Figgo sans souci, et je me suis attaqué à celle de ProjeQtOr.

    Et là, j'ai un petit problème de conversion.
    J'ai bien des solutions pour contourner le problème, mais j'aimerais le résoudre proprement plutôt...

    L'API de ProjeQtOr ne respecte pas correctement le typage JSON.
    Ainsi, il m'envoie les types numériques entre doubles quotes :

    Code json : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
     
    {
        "name": "Dupont",
        "age": "42"
    }

    Ce qui fait que dans mon code, si je fais simplement :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    class User
    {
        [JsonPropertyName("name")]
        public string Name { get; set; }
     
        [JsonPropertyName("age")]
        public int Age { get; set; }
    }

    Ca me saute à la figure en disant qu'il n'arrive pas à convertir un string en int (il se foule pas trop faut dire...)

    Je pensais trouver aisément une solution pour lui faire comprendre que "age" est un int sérialisé en string, quitte à devoir spécifier une fonction de conversion... Mais pas moyen de trouver un exemple...

    Les seules solutions que je trouve sur le net, c'est de créer "Age" en string, puis de créer une seconde propriété int avec getter qui retourne la version convertie... Mais je trouve ça crade, je préfère directement stocker un int pour travailler ensuite dessus plutôt que de le convertir à postériori...

    Y'a peut-être moyen de faire un getter/setter sur "Age" pour stocker directement en int, mais à nouveau, avoir deux propriétés pour la même valeur je trouve ça crade...

  10. #10
    Expert éminent sénior

    Avatar de François DORIN
    Homme Profil pro
    Consultant informatique
    Inscrit en
    Juillet 2016
    Messages
    2 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 40
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Consultant informatique
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juillet 2016
    Messages : 2 761
    Points : 10 543
    Points
    10 543
    Billets dans le blog
    21
    Par défaut
    Avec des JsonConverter personnalisés cela devrait être possible.

    J'avais déjà eu à faire cela pour le gérer sur une classe et non sur une propriété, mais je pense que le principe doit être plus ou moins le même.

  11. #11
    Expert éminent
    Avatar de StringBuilder
    Homme Profil pro
    Chef de projets
    Inscrit en
    Février 2010
    Messages
    4 170
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 45
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Chef de projets
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2010
    Messages : 4 170
    Points : 7 422
    Points
    7 422
    Billets dans le blog
    1
    Par défaut
    Suffit que j'arrête de chercher pour poser ma question pour que je trouve la réponse tout seul comme un grand

    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
            internal class User
            {
                public const string PATH = "Resource";
     
                [JsonPropertyName("id")]
                [JsonConverter(typeof(Common.JsonStringToInt))]
                public int Id { get; set; }
     
                [JsonPropertyName("name")]
                public string Name { get; set; }
            }

    Avec le converter :
    Code csharp : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
        internal class JsonStringToInt : JsonConverter<int>
        {
            public override int Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) 
                => int.Parse(reader.GetString()!, CultureInfo.InvariantCulture);
     
            public override void Write(Utf8JsonWriter writer, int intValue, JsonSerializerOptions options) 
                => writer.WriteStringValue(intValue.ToString(CultureInfo.InvariantCulture));
        }

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Réponses: 9
    Dernier message: 18/06/2011, 18h13
  2. [POO] ajouter des données dans un tableau contenant une structure
    Par Peanut dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 24/02/2009, 18h41
  3. Objet contenant une collection
    Par hacksi dans le forum Langage
    Réponses: 2
    Dernier message: 28/02/2008, 13h11
  4. Serialisation d'objet contenant une collection
    Par Invité dans le forum Langage
    Réponses: 5
    Dernier message: 21/08/2006, 08h37
  5. Réponses: 5
    Dernier message: 09/07/2006, 18h40

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo