DéveloppeurWeb.Com
    DéveloppeurWeb.Com
    • Agile Zone
    • AI Zone
    • Cloud Zone
    • Database Zone
    • DevOps Zone
    • Integration Zone
    • Web Dev Zone
    DéveloppeurWeb.Com
    Home»Uncategorized»JSON dans Kotlin – DZone
    Uncategorized

    JSON dans Kotlin – DZone

    février 27, 2023
    JSON dans Kotlin - DZone
    Share
    Facebook Twitter Pinterest Reddit WhatsApp Email

    Dans tout service Web qui reçoit et transmet des données vers et depuis un serveur, les premier et dernier événements transformeront généralement les données du format utilisé par la requête Web dans le format que le serveur Web gérera, et vice versa ; ces opérations sont appelées respectivement désérialisation et sérialisation. Pour certains services web, la réflexion portée sur cette partie du flux de données se concentre uniquement sur la façon de configurer le mécanisme de sérialisation pour qu’il fonctionne correctement. Cependant, il existe certains scénarios pour lesquels chaque cycle de processeur compte, et plus le mécanisme de sérialisation peut fonctionner rapidement, mieux c’est. Cet article explore les caractéristiques de développement et de performance de quatre options différentes pour travailler avec la sérialisation des messages JSON : GSON, Jackson, JSON-B et Kotlinx Serialization, en utilisant à la fois le langage de programmation Kotlin et certaines des fonctionnalités uniques que Kotlin offre par rapport à son langage homologue, Java.

    Installation

    Depuis sa première version en 2017, Kotlin s’est développé à pas de géant au sein de la communauté JVM, devenant le langage de programmation incontournable pour le développement Android ainsi qu’un citoyen de premier ordre dans les principaux outils JVM comme Spring, JUnit, Gradle, etc. . Parmi les innovations qu’il a apportées à la communauté JVM par rapport à Java, il y avait la classe de données, un type spécial de classe qui doit être utilisé principalement en tant que détenteur de données (en d’autres termes, un objet de transfert de données, ou DTO) et génère automatiquement la base fonctions utilitaires pour la classe comme equals(), hashcode(), copy(), et plus. Cela constituera la base des classes qui seront utilisées pour les tests de performance, dont la première est PojoFoo. « Pojo » signifie « Plain Old Java Object », signifiant utiliser uniquement les types de classe de base du langage de programmation Java :

    data class PojoFoo(var fizz: String, var bizz: Int, var bazz: List<String>) {
       constructor() : this("", 0, emptyList())
    }

    Pour ceux qui ne connaissent pas le langage de programmation Kotlin : la classe a trois attributs :

    1. fizz
    2. bizz
    3. bazz

    Qui contiennent à la fois des fonctions getter et setter. Il existe deux constructeurs pour la classe :

    1. Un qui nécessite des arguments pour chacun des attributs.
    2. Un qui ne nécessite aucun argument et remplit les attributs avec des valeurs par défaut.

    Ce deuxième constructeur est le « constructeur sans argument » qui est généralement requis par les mécanismes de sérialisation JSON.

    Dans l’exemple ci-dessus, les trois attributs de classe sont marqués avec le mot-clé var; cela signifie que les attributs sont modifiables et peuvent être modifiés à tout moment pendant la durée de vie d’une instance de la classe. Pour rendre les attributs immuables, il suffit de changer le désignateur en valsur lequel les attributs deviendront l’équivalent de final attributs en Java, et Kotlin ne générera plus de fonction getter pour les attributs. De plus, cela supprime l’exigence d’un constructeur sans argument, ce qui peut être éliminé du code :

    data class ImmutableFoo(val fizz: String, val bizz: Int, val bazz: List<String>)

    La prochaine classe d’exemple—DefaultValueFoo— utilise une valeur par défaut pour l’attribut fizz. Cela signifie que, si le constructeur de DefaultValueFoo est invoqué et qu’aucun argument n’est fourni pour fizz, alors l’argument se verra attribuer la valeur par défaut :

    data class DefaultValueFoo(var fizz: String = "FUZZ", var bizz: Int, var bazz: List<String>) {
       constructor() : this(bizz = 0, bazz = emptyList())
    }

    Enfin, la classe d’exemple ValueClassFoo change le type d’attribut bizz d’un entier simple à une classe inline. Les classes en ligne fonctionnent comme des enveloppes autour d’une seule valeur de « charge utile » ; tandis que le code Kotlin traitera la classe inline comme une classe « authentique », le compilateur traduira le code afin que seule la valeur de la charge utile soit présente. Cela offre plusieurs avantages par rapport à la simple utilisation directe de la valeur de charge utile, comme l’application d’une sécurité de type pour différentes variables, par exemple en spécifiant un nom d’utilisateur et un type de mot de passe – deux types qui seraient normalement tous deux des chaînes – pour une fonction de connexion. Dans ce cas, il permet l’utilisation de UInt: une classe exclusive à Kotlin qui simule le comportement d’une fonction non signée, ce qui n’est pas supporté par défaut par la JVM :

    data class ValueClassFoo(var fizz: String, var bizz: UInt, var bazz: List<String>) {
       constructor() : this("", 0u, emptyList())
    }

    Note: la classe est nommée comme telle car alors que les classes inline sont toujours appelées comme telles dans la documentation de Kotlin, elles ont été renommées en tant que classes de valeur dans le code réel ; le mot clé inline est obsolète.

    Les concurrents

    GSON

    Introduit en 2008 et développé par Google, GSON est l’une des principales options que les utilisateurs de Java utilisent pour effectuer la sérialisation entre les chaînes JSON et les objets Java et est la bibliothèque préférée à exploiter dans le développement Android grâce au support de Google.

    Usage

    L’utilisation de base est de construire une instance de Gson et invoquer les fonctions Gson.toJson() et Gson.fromJson() pour sérialiser un objet et désérialiser une chaîne JSON, respectivement.

    Travailler avec Kotlin

    Étonnamment, aucune étape supplémentaire n’est nécessaire pour travailler avec les quatre classes d’exemple ; tous les extraits de code fournis ci-dessus provenaient du code de test GSON.

    Jackson

    Introduite en 2009, Jackson est l’autre bibliothèque de sérialisation JSON largement utilisée – aux côtés de GSON – et est utilisée par défaut dans les principaux écosystèmes JVM comme le framework Spring.

    Usage

    L’utilisation de base est de construire une instance de ObjectMapper et invoquer les fonctions ObjectMapper.writeValueAsString() et ObjectMapper.readValue() pour sérialiser un objet et désérialiser une chaîne JSON, respectivement.

    Travailler avec Kotlin

    Contrairement à GSON, il y a pas mal de travail qui est nécessaire pour prendre en charge les fonctionnalités Kotlin dans les exemples de classes :

    • Jackson n’a pas de concept natif de désérialisation des classes qui ne possèdent pas de constructeur sans argument ; s’il ne trouve pas de constructeur sans argument, il lèvera normalement une exception. Une solution de contournement consiste à marquer les paramètres dans le constructeur avec @JsonProperty pour que Jackson sache quel argument correspond à quel attribut de classe :
    data class ImmutableFoo(
       @param:JsonProperty("fizz") val fizz: String,
       @param:JsonProperty("bizz") val bizz: Int,
       @param:JsonProperty("bazz") val bazz: List<String>
    )

    • Les classes en ligne ne sont pas traitées correctement en raison d’une différence dans la façon dont Jackson calcule comment effectuer la sérialisation et la désérialisation sur une classe. Un avantage de ces bibliothèques de sérialisation est qu’elles ne nécessitent normalement pas la création de classes spécialisées pour effectuer les actions de sérialisation et de désérialisation sur une classe. Au lieu de cela, ils calculent les champs à partir desquels extraire les valeurs et les définissent par réflexion ; alors que GSON exécute les actions de réflexion sur les champs d’attributs réels dans la classe cible, les actions de réflexion de Jackson sont ciblées sur les fonctions getter et setter des attributs. Il s’agit d’un problème avec les classes inline, car toute fonction qui accepte ou renvoie une classe inline est mutilée pour éviter les collisions avec des fonctions qui pourraient accepter le type « normal » équivalent dans la JVM. Ainsi, la sérialisation et la désérialisation des classes avec des attributs de classe en ligne s’avéreront problématiques :
    // Attempting to serialize to JSON
    expected: <{"fizz":"FUZZ","bizz":5,"bazz":["BUZZ","BOZZ"]}> but was: <{"fizz":"FUZZ","bazz":["BUZZ","BOZZ"],"bizz-pVg5ArA":5}>
    // Attempting to deserialize from JSON
    Unrecognized field "bizz" (class com.severett.serializationcomparison.jackson.model.ValueClassFoo), not marked as ignorable (3 known properties: "fizz", "bizz-WZ4Q5Ns", "bazz"])

    Bien qu’il existe un module spécialisé pour Jackson— jackson-module-kotlin— qui prend en charge de nombreuses parties de Kotlin qui ne sont pas incluses dans les tests ici (par exemple, Pair, Triple, IntRange, etc.), il ne fournit pas de support pour les classes en ligne et ne prévoit pas d’offrir de support dans un avenir prévisible. Au lieu de cela, il est nécessaire de créer des classes personnalisées de sérialiseur et de désérialiseur pour gérer ValueClassFoo et marquer ValueClassFoo avec @JsonSerialize et @JsonDeserializerespectivement:

    class ValueClassFooSerializer : JsonSerializer<ValueClassFoo>() {
       override fun serialize(value: ValueClassFoo, gen: JsonGenerator, serializers: SerializerProvider?) {
           gen.writeStartObject()
           gen.writeStringField(ValueClassFoo.FIZZ_FIELD, value.fizz)
           gen.writeNumberField(ValueClassFoo.BIZZ_FIELD, value.bizz.toInt())
           gen.writeArrayFieldStart(ValueClassFoo.BAZZ_FIELD)
           value.bazz.forEach(gen::writeString)
           gen.writeEndArray()
           gen.writeEndObject()
       }
    }
    
    class ValueClassFooDeserializer : JsonDeserializer<ValueClassFoo>() {
       override fun deserialize(jsonParser: JsonParser, ctxt: DeserializationContext?): ValueClassFoo {
           val node = jsonParser.codec.readTree<JsonNode>(jsonParser)
           return ValueClassFoo(
               fizz = node[ValueClassFoo.FIZZ_FIELD].asText(),
               bizz = node[ValueClassFoo.BIZZ_FIELD].asInt().toUInt(),
               bazz = (node[ValueClassFoo.BAZZ_FIELD] as ArrayNode).map { it.textValue() }
           )
       }
    }
    
    @JsonSerialize(using = ValueClassFooSerializer::class)
    @JsonDeserialize(using = ValueClassFooDeserializer::class)
    data class ValueClassFoo(var fizz: String, var bizz: UInt, var bazz: List<String>) {
       constructor() : this("", 0u, emptyList())
    
       companion object {
           const val FIZZ_FIELD = "fizz"
           const val BIZZ_FIELD = "bizz"
           const val BAZZ_FIELD = "bazz"
       }
    }

    JSON-B

    Relativement nouveau dans le monde Java – ayant été publié pour la première fois en 2017 aux côtés de JEE 8 – JSON-B est une norme officielle pour la sérialisation et la désérialisation du format de données JSON. L’API utilise Eclipse Yasson ou Apache Johnzon comme implémentation sous-jacente, ce qui signifie que l’une ou l’autre de ces bibliothèques devrait être …

    Share. Facebook Twitter Pinterest LinkedIn WhatsApp Reddit Email
    Add A Comment

    Leave A Reply Cancel Reply

    Catégories

    • Politique de cookies
    • Politique de confidentialité
    • CONTACT
    • Politique du DMCA
    • CONDITIONS D’UTILISATION
    • Avertissement
    © 2023 DéveloppeurWeb.Com.

    Type above and press Enter to search. Press Esc to cancel.