Annuaire d'articles
1. Convertissez n'importe quel objet en carte
inline fun <reified T : Any> T.asMap() : Map<String, Any?> {
val props = T::class.memberProperties.associateBy {
it.name }
return props.keys.associateWith {
props[it]?.get(this) }
}
2. Utilisez ObjectMapper pour convertir des objets
2.1 Convertir un objet en JsonString
data class Person(val name: String, var age: Int)
fun obj2JsonString(obj: Person){
val objectMapper = ObjectMapper().registerModule(JavaTimeModule()).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
return objectMapper.writeValueAsString(person)
}
2.2 JsonString pour objecter
data class Person(val name: String = " ", var age: Int = 23)
fun getPersonFromJsonString(): Person {
val objectMapper = ObjectMapper().registerModule(JavaTimeModule()).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
val jsonString = "{\"name\":\"tom\",\"age\":34}"
return objectMapper.readValue(jsonString, Person::class.java)
}
Remarque :
Vous pouvez voir que chaque champ de la classe de données a ici une valeur par défaut. Dans le cas contraire, une erreur sera signalée :
Exception in thread "main" com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of `com.example.Person` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)
at [Source: (String)"{"name":"tom","age":34}"; line: 1, column: 2]
at com.fasterxml.jackson.databind.exc.InvalidDefinitionException.from(InvalidDefinitionException.java:67)
at com.fasterxml.jackson.databind.DeserializationContext.reportBadDefinition(DeserializationContext.java:1615)
at com.fasterxml.jackson.databind.DatabindContext.reportBadDefinition(DatabindContext.java:400)
at com.fasterxml.jackson.databind.DeserializationContext.handleMissingInstantiator(DeserializationContext.java:1077)
at com.fasterxml.jackson.databind.deser.BeanDeserializerBase.deserializeFromObjectUsingNonDefault(BeanDeserializerBase.java:1332)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserializeFromObject(BeanDeserializer.java:331)
at com.fasterxml.jackson.databind.deser.BeanDeserializer.deserialize(BeanDeserializer.java:164)
at com.fasterxml.jackson.databind.ObjectMapper._readMapAndClose(ObjectMapper.java:4524)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3466)
at com.fasterxml.jackson.databind.ObjectMapper.readValue(ObjectMapper.java:3434)
En effet, il manque un constructeur sans paramètre et la classe de données ne génère pas de constructeur sans paramètre. Une valeur par défaut doit être ajoutée pour chaque paramètre afin de générer un constructeur sans paramètre. Sur le site officiel de Kotlin,
des valeurs par défaut sont ajoutées à chaque attribut de chaque classe de données. Quelle chose ennuyeuse ! Voulez-vous écrire sur chacun d’eux ? Je ne veux pas de toute façon.
Heureusement, Kotlin a officiellement une solution :
utilisez le plug-in de compilation sans argument et effectuez la configuration suivante dans le fichier pom :
<plugin>
<artifactId>kotlin-maven-plugin</artifactId>
<groupId>org.jetbrains.kotlin</groupId>
<version>${kotlin.version}</version>
<configuration>
<compilerPlugins>
<!-- Or "jpa" for JPA support -->
<plugin>no-arg</plugin>
</compilerPlugins>
<pluginOptions>
<option>no-arg:annotation=com.my.Annotation</option>
<!-- Call instance initializers in the synthetic constructor -->
<!-- <option>no-arg:invokeInitializers=true</option> -->
</pluginOptions>
</configuration>
<dependencies>
<dependency>
<groupId>org.jetbrains.kotlin</groupId>
<artifactId>kotlin-maven-noarg</artifactId>
<version>${kotlin.version}</version>
</dependency>
</dependencies>
</plugin>
2.3 JsonString contient une liste
Si la chaîne json contient une liste, elle doit être écrite comme :
data class Person(val name: String = " ", var age: Int = 23)
fun getPersonFromJsonString(): List<*> {
val objectMapper = ObjectMapper().registerModule(JavaTimeModule()).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
val jsonString = "[{\"name\":\"tom\",\"age\":34},{\"name\":\"tom\",\"age\":34}]"
return objectMapper.readValue(jsonString, List::class.java)}
Cependant, dans la liste ainsi obtenue, les éléments de la liste ne sont pas reconnus, mais sont stockés dans la liste sous forme de linkedHashMap. Si je veux supprimer un type d’objet spécifique, cela devrait ressembler à ceci :
data class Person(val name: String = " ", var age: Int = 23)
fun getPersonFromJsonString(): List<*> {
val objectMapper = ObjectMapper().registerModule(JavaTimeModule()).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS)
val jsonString = "[{\"name\":\"tom\",\"age\":34},{\"name\":\"tom\",\"age\":34}]"
var people: List<Person> = objectMapper.readValue(jsonString, objectMapper.typeFactory.constructCollectionType(List::class.java, Person::class.java))
return people
De cette façon, vous pouvez obtenir les instances spécifiques contenues dans la liste.