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

Services Web Java Discussion :

PATCH et rfc7396


Sujet :

Services Web Java

  1. #1
    Futur Membre du Club
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2017
    Messages : 4
    Points : 6
    Points
    6
    Par défaut PATCH et rfc7396
    Bonjour,

    Je cherche à implémenter un service REST PATCH en JAVA, qui respecte la rfc7396 (https://tools.ietf.org/html/rfc7396 ).

    Cette rfc définit que si on a un objet défini comme ceci:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    {
         "a": "b",
         "c": {
           "d": "e",
           "f": "g"
         }
      }
    Alors on peut modifier le champ a et supprimer le champ f, sans toucher à la valeur des autres champs, en envoyant ce json:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
      {
         "a":"z",
         "c": {
           "f": null
         }
       }

    On peut donc remarquer que:
    • Si le champ est absent dans le json, aucune modification n'est effectuée
    • Si le champ est présent dans le json mais null, la valeur champ est supprimée
    • Si le champ est présent dans le json et non null, la valeur du champ est remplacée


    Seulement voilà, lors de la déserialisation du json, on perd la différence entre l'absence de la valeur dans le json et sa présence en null. Dans les deux cas, la valeur attribuée au champ de l'objet java est null.
    J'utilise la balise @RequestBody avec un dto représentant mon json complet pour effectuer cette déserialisation, comme utilisée ici: https://www.baeldung.com/http-put-pa...ference-spring

    J'ai trouvé une solution, qui consiste à passer tous les champs java du dto au type Optional<T>, comme garretwilson ici https://github.com/FasterXML/jackson...ment-385266611
    Émettons que l'on ait un champ Optional<String> toto dans le dto, alors lors de la déserialisation, on a:
    • Si le champ est absent dans le json, toto est null
    • Si le champ est présent dans le json mais null, toto n'est pas null mais est vide
    • Si le champ est présent dans le json et non null, toto n'est pas null et contient la valeur du champ

    C'est pas mal car on peut faire la différence entre l'absence du json et la présence null, mais on se retrouve avec un objet de type Optional<T> pouvant être null, ce qui est une mauvaise pratique.

    Comment auriez-vous fait? Connaissez-vous une manière plus propre de procéder?

    Merci pour votre aide

  2. #2
    Futur Membre du Club
    Femme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Août 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Femme
    Localisation : France, Yvelines (Île de France)

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Août 2017
    Messages : 4
    Points : 6
    Points
    6
    Par défaut
    Je vais vous faire un petit retour sur la solution mise en place

    Finalement, il est nécessaire de n'effacer que les champs String et ça simplifie bien les choses.
    Au lieu d'envoyer null, on peut envoyer une chaine de caractères vide:
    La chaine de caractère n'étant pas null, le Java la récupère bien.
    La chaîne étant vide, la base de donnée vide la valeur.

    Ouf!

    Je laisse le sujet ouvert, au cas où quelqu'un trouve une solution plus universelle, notamment pour les Boolean et les nombres.

  3. #3
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 54
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Points : 29 131
    Points
    29 131
    Billets dans le blog
    2
    Par défaut
    Salut,

    Ta solution ne respecte pas la RFC du coup... Personnellement, j'opterais pour l'une de ces trois solutions:

    1. pas de désérialization en objet, juste du streaming, ce qui limiterait l'empreinte mémoire en cas de "gros" json, avec toute fois une grosse difficulté pour streamer le json à modifier et le json de patch en même temps, sans être obligé de faire un buffer local pour l'un des deux.
    2. de la désérialization vers un objet spécifique, mappant des clefs et des actions, au lieu de clefs et valeurs à interpréter. En plus avec des actions, on peut traiter l'application sur un objet du type org.json.JSONObject, ou com.google.gson.JsonObject. On peut toujours streamer le json à modifier...
    3. Sinon, il y a toujours la désérialization en "jsonobject" de l'api qu'on veut (org.json, Jackson, GSon...) dont les classes permettent de distinguer la présence ou la valeur "NULL"...

      A noter, qu'on peut s'inspirer de ce qui est fait dans org.json pour traiter cette distinction : la valeur "NULL" n'est pas null, mais un singleton de java.lang.Object. Dans une API à la Gson, ce sera une méthode de test (genre isNull()). On est toutefois obligé d'utiliser un Optionnal<Object>. Pour résoudre ça, soit on fait plusieurs valeurs de "NULL", une pour chaque type, ou on utilise un wrapper, comme le JsonElement de GSon.
      Ainsi, on pourra faire
      Code : Sélectionner tout - Visualiser dans une fenêtre à part
      1
      2
      3
      4
      5
      6
      7
      8
       
      Optional<JsonElement> value = json.getValue(fieldname);
      if ( !value.isPresent() ) {
           // clef inexistente
      }
      else if ( opt.filter(JsonElement::isJsonNull).isPresent() ) {
          // valeur null
      }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

Discussions similaires

  1. Problème avec patch
    Par stephgourich dans le forum Linux
    Réponses: 3
    Dernier message: 20/04/2005, 14h16
  2. Réponses: 1
    Dernier message: 09/03/2005, 19h40
  3. Patch modifiant l'offset d'un .exe
    Par Goshi dans le forum VB 6 et antérieur
    Réponses: 5
    Dernier message: 18/02/2005, 18h24
  4. [Apache] Patches Sécurité
    Par orafrance dans le forum Oracle
    Réponses: 4
    Dernier message: 08/10/2004, 15h38
  5. Comment on patch un .configure ?
    Par Shrieker dans le forum Linux
    Réponses: 2
    Dernier message: 21/04/2004, 12h35

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